How to initialize an array of structs

I want to create an array of structs like shown below

mutable struct mystruct
    a::Float32
    b::Float32
    c::UInt32
end

mystruct() = mystruct(0,0,0)

size = 3

a = Array{mystruct, 3}(undef, size, size, size)


for i in eachindex(a)
    a[i] = mystruct()
end

Is there anyway to initialize the structs in the array without looping over the array? For instance something like:

a = Array{mystruct, 3}({0,0,0}, size, size, size)
# or
a = Array{mystruct, 3}(mystruct(), size, size, size)

Technically there’s going to be an underlying loop somewhere, but the fill(x, dims...) and fill!(A, x) methods do this. Just bear in mind that they assign the same single instance x to all the elements, so if the instance is mutable and you mutate it, all the elements see the change.

If you want each element to have different instances, an explicit loop is the general way, but judging from your example, you could reasonably define a Base.zero(::Type{mystruct}) = mystruct(0,0,0) method, then call zeros(mystruct, dims...). Note that zeros takes the type instead of an instance as an argument, so it can do zero(mystruct) in the underlying loop to make a new instance per element.

Or a comprehension:

[ mystruct() for _ in 1:n1, j in _ 1:n2, k in _ 1:n3 ]
6 Likes

Note that a comprehension evaluates mystruct(), or whatever code you write there, per iteration just like a for-loop body, so each element gets a different instance. Although it may look more similar to the fill(mystruct(), dims...) call at a glance, the difference there is mystruct() get evaluated only once, then the returned instance is passed as an argument into a fill call.

2 Likes

Sure, if the structure is mutable most likely different instances is what the OP wants.

Thanks for your input. I understand there is going to be a loop somewhere I just wanted a convenient way to make initialize it without having to explicitly write the loop.

Different instances for each element is what I want so either defining a new zero function or the comprehension is the answer.

You can simply use dot assigment with a scalar on the right side:

a .= Ref(mystruct(0,0,0))

That will still assign the same instance to every index.

2 Likes