Nested list comprehensions in Julia

混江龙づ霸主 提交于 2019-12-21 04:21:41

问题


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?


回答1:


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



回答2:


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



回答3:


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:


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:


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))


来源:https://stackoverflow.com/questions/21129125/nested-list-comprehensions-in-julia

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!