List of concepts and tuples in Julia

I am trying to do in Julia what this Python code does. (Find all pairs from two lists whose total value exceeds 7.)

#Python def sum_is_large(a, b): return a + b > 7 l1 = [1,2,3] l2 = [4,5,6] l3 = [(a,b) for a in l1 for b in l2 if sum_is_large(a, b)] print(l3) 

In Julia there is no β€œif” to understand the lists. And if I use filter (), I'm not sure if I can pass two arguments. Therefore my best suggestion is:

 #Julia function sum_is_large(pair) a, b = pair return a + b > 7 end l1 = [1,2,3] l2 = [4,5,6] l3 = filter(sum_is_large, [(i,j) for i in l1, j in l2]) print(l3) 

I do not find this very attractive. So my question is: is there a better way in Julia?

+5
source share
6 answers

Using the very popular package Iterators.jl, in Julia:

 using Iterators # install using Pkg.add("Iterators") filter(x->sum(x)>7,product(l1,l2)) 

- an iterator producing pairs. So, to get the same printout as the OP:

 l3iter = filter(x->sum(x)>7,product(l1,l2)) for p in l3iter println(p); end 

The iterative approach is potentially much more efficient in terms of memory. Of course, one could just l3 = collect(l3iter) get a pair vector.

@ user2317519, just curious if there is an equivalent form of an iterator for python?

+6
source

Guards ( if ) are now available in Julia v0.5 (currently at the release selection stage):

 julia> v1 = [1, 2, 3]; julia> v2 = [4, 5, 6]; julia> v3 = [(a, b) for a in v1, b in v2 if a+b > 7] 3-element Array{Tuple{Int64,Int64},1}: (3,5) (2,6) (3,6) 

Note that generators are now available:

 julia> g = ( (a, b) for a in v1, b in v2 if a+b > 7 ) Base.Generator{Filter{##18#20,Base.Prod2{Array{Int64,1},Array{Int64,1}}},##17#19}(#17,Filter{##18#20,Base.Prod2{Array{Int64,1},Array{Int64,1}}}(#18,Base.Prod2{Array{Int64,1},Array{Int64,1}}([1,2,3],[4,5,6]))) 
+3
source

Another option, similar to @DanGetz parameter, also using Iterators.jl :

 function expensive_fun(a, b) return (a + b) end 

Then, if the condition is also complicated, it can be defined as a function:

 condition(x) = x > 7 

Finally, filter the results:

 >>> using Iterators >>> result = filter(condition, imap(expensive_fun, l1, l2)) 

result is an iterable that can only be calculated if necessary (inexpensive) and can be collected collect(result) if necessary.

Single line if the filter condition is quite simple:

 >>> result = filter(x->(x > 7), imap(expensive_fun, l1, l2)) 

Note: imap works initially for an arbitrary number of parameters.

+2
source

Maybe something like this:

 julia> filter(pair -> pair[1] + pair[2] > 7, [(i, j) for i in l1, j in l2]) 3-element Array{Tuple{Any,Any},1}: (3,5) (2,6) (3,6) 

although I would agree that it doesn’t look like it should be the best way ...

+1
source

I am surprised that no one mentions a ternary operator to execute a conditional:

 julia> l3 = [sum_is_large((i,j)) ? (i,j) : nothing for i in l1, j in l2] 3x3 Array{Tuple,2}: nothing nothing nothing nothing nothing (2,6) nothing (3,5) (3,6) 

or even a normal normal if block inside a compound statement, i.e.

 [ (if sum_is_large((x,y)); (x,y); end) for x in l1, y in l2 ] 

which gives the same result.

I feel that this result makes much more sense than filter() , because in julia the construction a in A, b in B interpreted by size, and therefore the output is actually an "understanding of the array" with the corresponding dimension, which is clearly In many cases, it would be beneficial and presumably desirable behavior (whether we include conditional or not).

While the filter will always return a vector. Obviously, if you really need a vector result, you can always collect to get the result; or to understand a conditional list such as here, you can simply remove the nothing elements from the array by doing l3 = l3[l3 .!= nothing] .

Presumably, this is still clearer and no less efficient than the filter() approach.

0
source

You can use the @vcomp (vector understanding) macro in VectorizedRoutines.jl to make Python-like understandings:

 using VectorizedRoutines Python.@vcomp Int[i^2 for i in 1:10] when i % 2 == 0 # Int[4, 16, 36, 64, 100] 
0
source

Source: https://habr.com/ru/post/1246167/


All Articles