# How to change/reduce vector of Structure to be a structure of aggregated fields?

**URL:** <https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032>\
**Category:** General Usage\
**Tags:** question\
**Created:** [March 17, 2022, 3:48pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032 "2022-03-17T15:48:04Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [March 17, 2022, 3:48pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/1 "2022-03-17T15:48:04Z")

</div>

I have a file that I can read from it a specific structure `Rs` and its instance `R` (a simple MWE of it is below)

```julia
using LinearAlgebra, Parameters, Base
Base.@kwdef mutable struct Rs
    I::Vector{Float64} = [2,2,2]
    Dot::Array{Float64, 2} = [1 1 1; 2 2 2; 3 3 3]
end
R = Rs[];
push!(R, Rs());
push!(R, Rs()); 
julia> R
2-element Vector{Rs}:
 Rs([2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])
 Rs([2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])

```

I want to create `RR` to be of Rs, in which each field of `RR` is the aggregated vector/array of the field rows of `R`, i.e.,

```julia
RR = Rs(reduce(vcat, getproperty(r, :I) for r in R), reduce(vcat, getproperty(r, :Dot) for r in R));
julia> RR
Rs([2.0, 2.0, 2.0, 2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0; 1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])

```

The previous way is working. However, the fields of `Rs` are a lot. So, is there an alternative easier way to build `RR` rather than long command i.e., `RR = Rs(reduce(..),reduce(..), reduce(..)..)`?

Another issue is; if I want to do some operations (such as below), working on `RR` or `R` would be faster?

```julia
for i in eachindex(R)
    for j in 1:3
         R[i].I[j] = R[1].Dot [j,1];
    end
end

for i in 1:length(R.I)/3
    for j in 1:3
         R.I[3*i+j-3] = R.Dot [3*i+j-3,1];
    end
end
```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [March 17, 2022, 3:57pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/2 "2022-03-17T15:57:37Z")

</div>

You would probably get better help faster if you choose a more descriptive title of your post.

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [March 17, 2022, 3:59pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/3 "2022-03-17T15:59:38Z")

</div>

Thank you for your advice. I followed.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 17, 2022, 4:42pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/4 "2022-03-17T16:42:16Z")

</div>

I am not entirely sure I understood the question but are you aware of `propertynames` and the splat operator `...`? You can probably assemble a `Tuple` or `NamedTuple` which you can splat in the `Rs` constructor.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 17, 2022, 5:29pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/6 "2022-03-17T17:29:52Z")

</div>

No, I did believe `Tuple` or `NamedTuple` would be necessary intermediaries but I was wrong. This works:

```julia
RR = Rs((reduce(vcat, getfield.(R, pn)) for pn in fieldnames(Rs))...)

```

Of course, this requires that the reduction that you wanted to apply must be `vcat` for all fields.

About your loops, I suggest you benchmark both alternatives. Often details as how large are the elements, or if the compiler was able to employ vectorized assignment, impact what is the best alternative. Unless you know this to be a bottleneck I would go with the option that is most readable and less prone to break with future changes.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 18, 2022, 12:30am UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/8 "2022-03-18T00:30:19Z")

</div>

`StaticArrays` are recommended for small arrays (i.e., at most 100 elements), so I think that if you stick to your _many `struct`s with small arrays_ it may work, but if your plan is to combine them maybe `StaticArrays` are not adequate. Especially because then you cannot fix their length in the `struct` definition and therefore the fields will be abstract (more specifically `UnionAll`) throwing away any performance improvement. Only use `StaticArrays` if your arrays are small and always the same size as, for example, sets of three-dimensional coordinates or something like that.

About your code, please post an equivalent MWE, in which `RRs` has default values for fields and there is a vector if two of them already created, also node that you did not change `fieldnames(Rs)` in `RR = ...` to `fieldnames(RRs)`.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [March 18, 2022, 6:08am UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/9 "2022-03-18T06:08:45Z")

</div>

You may find `StructArrays` useful: they allow an efficient access to both individual structs (`RR[1]`), and to a field of all structs in the array (`RR.I`):

```julia
julia> using StructArrays

julia> RR = StructArray(R)
2-element StructArray(::Vector{Vector{Float64}}, ::Vector{Matrix{Float64}}) with eltype Rs:
 Rs([2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])
 Rs([2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])

julia> RR[1]
Rs([2.0, 2.0, 2.0], [1.0 1.0 1.0; 2.0 2.0 2.0; 3.0 3.0 3.0])

julia> RR.I
2-element Vector{Vector{Float64}}:
 [2.0, 2.0, 2.0]
 [2.0, 2.0, 2.0]

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 18, 2022, 3:07pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/12 "2022-03-18T15:07:49Z")

</div>

Why do you import `Parameters` if you use the non-exported `Base.@kwdef` that should be avoided?

You did not understood me, I offered to help after you sorted out your struct definition. Check the [`StaticArrays` QuickStart](https://github.com/JuliaArrays/StaticArrays.jl#quick-start) for the notation to be used. Create a MWE with the struct already converted and state your difficulty, but again, I am not sure if `StaticArrays` are what you want, in the case you want to keep aggregating many small structs in a single large `struct`.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 18, 2022, 4:53pm UTC](https://discourse.julialang.org/t/how-to-change-reduce-vector-of-structure-to-be-a-structure-of-aggregated-fields/78032/14 "2022-03-18T16:53:42Z")

</div>

How is the format of the data file? It is possible that you need to parse it by hand (i.e., write your custom parsing function).
