Nested List Comprehensions in Julia

In python I can do nested list comprehensions, for instance I can flatten the following array thus:

a = [[1,2,3],[4,5,6]]
[i for arr in a for i in arr]

to get [1,2,3,4,5,6]

If I try this syntax in Julia I get:

julia> a
([1,2,3],[4,5,6],[7,8,9])

julia> [i for arr in a for i in arr]
ERROR: syntax: expected ]

Are nested list comprehensions in Julia possible?

5 Answers

This feature has been added in julia v0.5:

julia> a = ([1,2,3],[4,5,6],[7,8,9])
([1,2,3],[4,5,6],[7,8,9])

julia> [i for arr in a for i in arr]
9-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
 8
 9

List comprehensions work a bit differently in Julia:

> [(x,y) for x=1:2, y=3:4]
2x2 Array{(Int64,Int64),2}:
 (1,3)  (1,4)
 (2,3)  (2,4)

If a=[[1 2],[3 4],[5 6]] was a multidimensional array, vec would flatten it:

> vec(a)
6-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6

Since a contains tuples, this is a bit more complicated in Julia. This works, but likely isn't the best way to handle it:

function flatten(x, y)
    state = start(x)
    if state==false
        push!(y, x)
    else
        while !done(x, state) 
          (item, state) = next(x, state) 
          flatten(item, y)
        end 
    end
    y
end
flatten(x)=flatten(x,Array(Any, 0))

Then, we can run:

> flatten([(1,2),(3,4)])
4-element Array{Any,1}:
 1
 2
 3
 4
4

You can get some mileage out of using the splat operator with the array constructor here (transposing to save space)

julia> a = ([1,2,3],[4,5,6],[7,8,9])
([1,2,3],[4,5,6],[7,8,9])

julia> [a...]'
1x9 Array{Int64,2}:
 1  2  3  4  5  6  7  8  9

Any reason why you're using a tuple of vectors? It's much simpler with arrays, as Ben has already shown with vec. But you can also use comprehensions pretty simply in either case:

julia> a = ([1,2,3],[4,5,6],[7,8,9]);
julia> [i for i in hcat(a...)]
9-element Array{Any,1}:
 1
 2
 ⋮

The expression hcat(a...) "splats" your tuple and concatenates it into an array. But remember that, unlike Python, Julia uses column-major array semantics. You have three column vectors in your tuple; is that what you intend? (If they were row vectors — delimited by spaces — you could just use [a...] to do the concatenation). Arrays are iterated through all elements, regardless of their dimensionality.

Don't have enough reputation for comment so posting a modification @ben-hammer. Thanks for the example of flatten(), it was helpful to me.

But it did break if the tuples/arrays contained strings. Since strings are iterables the function would further break them down to characters. I had to insert condition to check for ASCIIString to fix that. The code is below

    function flatten(x, y)
        state = start(x)
        if state==false
            push!(y, x)
        else
            if typeof(x) <: String
                push!(y, x)
            else 
                while (!done(x, state)) 
                    (item, state) = next(x, state) 
                    flatten(item, y)
                end
            end
        end
        y
    end
    flatten(x)=flatten(x,Array(Any, 0))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest