Extract a field from an array of structures

I was wondering if there is a more elegent way to extract a field from an array of structures. An example follows:


julia> struct Foo
           i::Int
           v::Vector{Int}
       end

julia> foo = Vector{Foo}(undef, 2)
2-element Vector{Foo}:
 #undef
 #undef

julia> foo[1] = Foo(1, [1, 2])
Foo(1, [1, 2])

julia> foo[2] = Foo(3, [6, 8])
Foo(3, [6, 8])

julia> foo
2-element Vector{Foo}:
 Foo(1, [1, 2])
 Foo(3, [6, 8])

julia> # obtain the first field of the vector of structures

julia> [foo[a].i  for a in 1:length(foo)]
2-element Vector{Int64}:
 1
 3

julia>

There is GitHub - JuliaArrays/StructArrays.jl: Efficient implementation of struct arrays in Julia

You can use broadcasting with either the getproperty or getfield functions:

julia> getproperty.(foo, :i)
2-element Vector{Int64}:
 1
 3

julia> getfield.(foo, :i)
2-element Vector{Int64}:
 1
 3

If you want to do it with a comprehension, this is shorter and better:

[x.i for x in foo]

Shorter it is, better is debatable. The broadcast solution is probably better situations in you want dot fusion to happen, and the StructArrays is a more general solution.

It absolutely is better than the indexing version. For one thing it doesn’t assume anything about the axes, and it does natural iteration.

English isn’t my first language but I thought I made it clear that I compared my proposal to the quoted comprehension approach. I had no intention to claim anything about its relative merits to other solutions.

I apologize, I must have read it fast. In retrospective, it is obvious that you are improving just on the previous comprehension solution. What seems to have caused my confusion is that I did not scroll down all of Jake’s code. So when I saw you were referring one previous alternative I thought you could only be referring to the broadcast or the package.