# How can I fill an array with empty 2D arrays?

Hello,
I am going into a loop which will produce N 2D arrays. I want to store them in an array, so I want to define it beforehand. I know the syntax for filling with empty 1D arrays but I can’t figure our the 2D version. Can you help me out?
Thanks

1D version that works
`mat3Dtt = fill(Float64[],1, N);`

2D version I can’t get to work

``````mat3Dtt = fill(Array{Float64,2},1, N);
julia> mat3Dtt=rand(3,3)
ERROR: MethodError: Cannot `convert` an object of type Array{Float64,2} to an object of type DataType
``````

You can do this, but be warned that `fill` repeats the same element, it doesn’t make copies.

``````julia> x = fill(Matrix{Float64}(undef,0,0), 3);

julia> x = reshape(1:6,2,3);

julia> x  # ok!
3-element Vector{Matrix{Float64}}:
[1.0 3.0 5.0; 2.0 4.0 6.0]
0×0 Matrix{Float64}
0×0 Matrix{Float64}

julia> y = fill(Matrix{Float64}(undef,2,3), 3);

julia> y === y
true

julia> y .= reshape(1:6,2,3);

julia> y
3-element Vector{Matrix{Float64}}:
[1.0 3.0 5.0; 2.0 4.0 6.0]
[1.0 3.0 5.0; 2.0 4.0 6.0]
[1.0 3.0 5.0; 2.0 4.0 6.0]
``````

But you may be better off just letting a comprehension, or `map`, create the output for you. Or doing `z = Matrix{Float64}[]; push!(z, reshape(1:6,2,3))`.

3 Likes

i will go with that, thank you very much!

If you’re replacing the entire array that’s fine, but if you intend to predefine and then fill them, it’s still a problem:

``````x = fill(Matrix{Float64}(undef,2,2), 3);

julia> x
3-element Vector{Matrix{Float64}}:
[2.75859452845e-313 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]
[2.75859452845e-313 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]
[2.75859452845e-313 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]

julia> x[1,1] = 5
5

julia> x
3-element Vector{Matrix{Float64}}:
[5.0 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]
[5.0 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]
[5.0 3.3951932658e-313; 2.33419537065e-313 6.94677762088306e-310]
``````

Make sure you understand @mcabbott’s warning:

That means you will get an array consisting of the same matrix 3 times. Modifying any one of those will modify all of them because they are all the same value. This is almost certainly not what you want in any application.

1 Like

Yeah, although if you’re doing that then pre-allocating the individual arrays is pointless, since they’ll be replaced regardless.

3 Likes

Yes, I am replacing the entire array, using it a bit like this:

``````julia> a=fill(Array{Float32,2}(undef,0,0),1,3);

julia> a=rand(2,2); a=rand(3,3);

julia> a[:]
3-element Array{Array{Float32,2},1}:
[0.92491776 0.93883944; 0.9667731 0.9894779]
[0.13091879 0.37846377 0.07404064; 0.71520746 0.9362733 0.41508183; 0.8309387 0.73587126 0.0631132]
Array{Float32}(undef,0,0)
``````

I understand that I could just push the new one as it is generated, however I think pre-allocating makes the code more readable as you know where each array is going to go beforehand, instead of counting how many pushes there are.

1 Like

I see. Then perhaps what you actually need is:

``````a = Array{Array{Float32, 2}, 1}(undef, 3)
``````

which is a `Vector` (a 1-D `Array`) whose elements are themselves matrices, with space allocated to hold 3 elements.

You can write that more simply as: `Vector{Matrix{Float32}}(undef, 3)` if you prefer.

4 Likes