Nested list comprehensions in Julia

前端 未结 5 1027
无人共我
无人共我 2021-02-13 16:14

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]


        
相关标签:
5条回答
  • 2021-02-13 16:20

    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
    
    0 讨论(0)
  • 2021-02-13 16:20

    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.

    0 讨论(0)
  • 2021-02-13 16:24

    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
    
    0 讨论(0)
  • 2021-02-13 16:25

    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
    
    0 讨论(0)
  • 2021-02-13 16:26

    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))
    
    0 讨论(0)
提交回复
热议问题