Nested list comprehensions in Julia

2019-03-26 06:08发布

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?

标签: julia
5条回答
我想做一个坏孩纸
2楼-- · 2019-03-26 06:19

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))
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-03-26 06:25

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
查看更多
劫难
4楼-- · 2019-03-26 06:30

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.

查看更多
等我变得足够好
5楼-- · 2019-03-26 06:34

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
查看更多
ゆ 、 Hurt°
6楼-- · 2019-03-26 06:41

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
查看更多
登录 后发表回答