Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List comprehensions and tuples in Julia

I am trying to do in Julia what this Python code does. (Find all pairs from the two lists whose combined value is above 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)

There is no if for list comprehensions in Julia. And if I use filter(), I'm not sure if I can pass two arguments. So my best suggestion is this:

#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 don't find this very appealing. So my question is, is there a better way in Julia?

like image 235
Jonatan Pallesen Avatar asked Mar 31 '16 15:03

Jonatan Pallesen


People also ask

Does list comprehension work for tuples?

A tuple comprehension is considered to be less fundamental than a list comprehension. So there is no special syntax dedicated for the same. Yet, if you want a tuple after applying comprehension, it can be achieved by wrapping a tuple around a generator object.

What is a tuple in Julia?

Tuples in Julia are an immutable collection of distinct values of same or different datatypes separated by commas. Tuples are more like arrays in Julia except that arrays only take values of similar datatypes. The values of a tuple can not be changed because tuples are immutable.

Is tuple comprehension faster than list comprehension?

There is no real tuple comprehension in Python. We can get very close to it in terms of syntax if we use the tuple class and generator tuple(i for i in iterable) . But it is slower than list comprehensions.


2 Answers

Guards (if) are now available in Julia v0.5 (currently in the release-candidate 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 also 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])))
like image 130
David P. Sanders Avatar answered Sep 30 '22 11:09

David P. Sanders


Another option similar to the one of @DanGetz using also 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

And last, filter the results:

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

result is an iterable that is only computed when needed (inexpensive) and can be collected collect(result) if required.

The one-line if the filter condition is simple enough would be:

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

Note: imap works natively for arbitrary number of parameters.

like image 43
Imanol Luengo Avatar answered Sep 30 '22 10:09

Imanol Luengo