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[1]=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[1] = 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[1] === y[2]
true
julia> y[1] .= 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,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[1]=rand(2,2); a[2]=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