# How to create and fill a vector of Struct as in a Matrix?

I have a struct of `Rs` and a vector `R` of it. Currently, I am using such the below code to construct R and then change the values of its fields.

``````Base.@kwdef mutable struct Rs
I::Vector{Float64} = [2,2,2]
Dot::Array{Float64, 2} = [0 0 0; 0 0 0; 0 0 0]
end
R = Rs[];
push!(R, Rs()); # the values of fields may change in the code
push!(R, Rs()); # the values of fields may change in the code
julia> R
2-element Vector{Rs}:
Rs([2.0, 2.0, 2.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])
Rs([2.0, 2.0, 2.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])
#Modify the values of the fields, such as
#R[index1].I[index2] = value;
``````

Is there any way to construct R and fill the values of its fields as in Matrix, such as below?

``````Base.@kwdef mutable struct Rs
I::Vector{Float64} = [2,2,2]
Dot::Array{Float64, 2} = [0 0 0; 0 0 0; 0 0 0]
end
R = Vector{Rs}[([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]);
([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])];
``````

maybe. (Note the dot)

1 Like

@leandromartinez98 Thank you!
I have tried but gave me an error:

``````julia> U = Rs.[([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]),
([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])]
ERROR: syntax: invalid syntax "Rs.[([5, 5, 4], [0 0 0; 0 0 0; 0 0 0]), ([3, 2, 7], [0 0 0; 0 0 0; 0 0 0])]" around REPL:1
Stacktrace:
 top-level scope
@ REPL:
``````

I think you want

``````R = map(args -> Rs(args...), [([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]);
([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])])
``````
3 Likes

Uhm… not sure why that does not work.

Edit: maybe just adding a parenthesis:

``````struct A x end
@show A.([1, 2])
``````

Works

1 Like

@stevengj Thank you! it works.
@lmiq @stevengj Do you think the structure of R is complicated in Julia and affect the performance?

If the arrays are that small, use Static Arrays

2 Likes

If you always have 3-component vectors and 3x3 matrices (or in general small vectors/matrices whose size is always the same, e.g. equal to the number of spatial dimensions in a geometry), then you should consider using StaticArrays.

2 Likes

@lmiq is it as below?

``````julia> X =Rs.([([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]),
([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])])
ERROR: MethodError: no method matching Rs(::Tuple{Vector{Float64}, Matrix{Float64}})
Closest candidates are:
Rs(::Any, ::Any) at REPL:2
Rs(; I, Dot) at util.jl:450
``````
1 Like

I see, I thought that would work… Cannot really test things now. If you use that often you may want a custom constructor then.

1 Like

I only need it once at the beginning of my code (input of my network data)

This is in a sense a mix of Leandro and Steve’s answers.

``````   Base.splat(Rs).([([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]);
([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])])
``````
2 Likes

The problem here is that the constructor does not take a single object that is a tuple of two values but instead it takes two separate objects. Unfortunately this means you cannot just use broadcast and apply the constructor element-wise to a single vector of two-element tuples but instead you need to apply the constructor element-wise to two vectors instead. I adapted the try above to the correct form below:

``````julia> R = Rs.(
[[5.0, 5.0, 4.0], [3.0, 2.0, 7.0]], # vector of first parameters
[[0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]] # vector of second parameters
)
2-element Array{Rs,1}:
Rs([5.0, 5.0, 4.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])
Rs([3.0, 2.0, 7.0], [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0])

``````
3 Likes