# Get the Vector of a Vector of struct

I have a vector of a struct and want a vector of a component of the struct:

``````struct MyPair
x::Float64
y::Float64
end

vec = Vector{MyPair}()
push!(vec, MyPair(1,10))
push!(vec, MyPair(2,20))
push!(vec, MyPair(3,30))

println(vec[:].x) # Doesn't compile.
println(vec.x[:]) # Doesn't compile, either.
``````

Does a functionality to do this already exist in Julia or in a Julia package?

I can easily write a function to extract the vector of the component but it’s a bit tedious to have to write such a function for each struct I define . . .

(Before introducing the struct, I was using a 2D array like arr[1,:] for vec.x and arr[2,:] for vec.y but I always get confused as to whether “1” represents “x” or not . . . The struct introduces an annotation, if you like.)

Are you looking for:

``````julia> getproperty.(vec, :x)
3-element Vector{Float64}:
1.0
2.0
3.0
``````

?

7 Likes

StructArrays.jl allows you to have an array which gives structs on iteration whilst internally storing individual fields in separate arrays.

2 Likes

You could also spit out the vector with a comprehension:

``````[v.x for v in vec0]
``````

NB: renamed `vec` to `vec0` to not collide with the Base function with the same name

3 Likes

Or, for completeness:

`` map (v -> getproperty(v,:x),vec)``
1 Like

Thank you all for your inputs. Each of your solutions, of course, works for my problem.

For completeness I have a related question.

I also have a vector of vectors. It’s of course very similar to a 2D array, but I use a vector of vectors because both the child and parent vectors individually grow as I read data from a file. The following code omits the reading-from-file part just for simplicity:

``````vv = Vector{Vector{Int}}()
push!(vv, [1, 2, 3])
push!(vv, [10, 20, 30])
println(vv[:]) # I want the first "column" [1, 10] but you actually get [1,2,3].
a = [1 2 3; 10 20 30]
println(a[:, 1]) # we get [1,10]
``````

So, what should we do to get the first “column” of a vector of vectors?

In my original question of this thread, we have `getproperty` such that

``````getproperty(s, :x) # is equivalent to s.x
``````

So, I imagine there may be a `getelement` function such that

``````getelement(v, 1) # equivalent to v
``````

If there is such a function, we would be able to get the first “column” of the vector of vectors as

``````getelement.(vv, 1)
``````

wouldn’t we?

Currently, I use the list comprehension `[v for v in vv]`, which is arguably easier to understand than the above. (That’s why I said “for completeness” . . . )

Broadcast `getindex()`, for example, to get the second element do: `getindex.(vv, 2)`

1 Like

Or in the special case of getting the first element from each, `first.(vv)`

1 Like

Thanks!!! But why getindex ? Although I saw the name somewhere, it’s never occurred to me that it actually gets an element from a vector . . .

Perhaps is it short for “get value from vv at index i” ? But if that was the intention, I would call it “get_at_index” at the very least . . .

1 Like

See the discussion here:

I guess the direct answer to your question is that name was just chosen in the early days of Julia and no one ever considered it “bad” enough to warrant a massively breaking change to the language later on. As you see in the discussion, there is a possibility that it might be renamed in 2.0.

If it’s about discoverability (i.e. you would have never guessed that `[]` is syntactic sugar for `getindex`), you can do:

``````julia> x = rand(5);

julia> Meta.@lower x
:(\$(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Base.getindex(x, 1)
└──      return %1
))))
``````

to see what’s going on.

2 Likes

See the discussion here

Wow, thanks! That discussion already includes everything I said: `getindex` being counterintuitive, `get element`, `get at index`, etc.

Believe me, I searched Google for the function name for `[ ]` but failed to find `getindex`, which was the reason why I posted my question here.

you would have never guessed that is syntactic sugar for getindex

Well, before posting my question, actually I tried

``````([]).(vv, 1)
``````

because I guessed the notation `[ ]` may be a syntactic sugar for a function call.

This is similar to how C++ and Haskell define syntactic sugars.

`Meta.@lower`

Reflection capability of Julia is amazing to me. Thanks for that.