How to initialize an array of AbstractArray?

How do I initialize a one-dimensional array, where each element of the array is a two-dimensional array?
For example, I need to initialize a one-dimensional array of length three :[[0 0, 0 0], [0 0 0, 0 0 0], [0 0 0, 0 0 0]], What should I do?

Here is one way:

julia> x = Vector{Matrix{Float64}}(undef, 3)
3-element Array{Array{Float64,2},1}:
 #undef
 #undef
 #undef

julia> x[1] = zeros(2,2);

julia> x[2] = zeros(3,3);

julia> x[3] = zeros(3,3);

julia> x
3-element Array{Array{Float64,2},1}:
 [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 0.0; 0.0 0.0 0.0]

Ok, thank you very much!

PS. If you’re working with lots of small (2x2 or 3x3) arrays and they are all the same size, consider an array of StaticArrays instead:

julia> using StaticArrays

julia> zeros(SMatrix{3,3,Float64,9}, 3)
3-element Array{SArray{Tuple{3,3},Float64,2,9},1}:
 [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]
 [0.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0]

They are much more efficient to work with than regular arrays for such small sizes.

(Note that neither this nor Vector{Matrix{Float64}}(undef, 3) is an "array of AbstractArray" as your title suggested — they are arrays of specific (“concrete”) AbstractArray subtypes. If you really want an array of AbstractArray, you could do what @fredrikekre suggested but with Vector{AbstractArray}(undef, 3). This has the advantage that the elements can be any type of array, but the disadvantage that it will be much slower to work with since the types aren’t known until runtime.)

4 Likes

Thank you for your comments and corrections

The advantage of this approach is that it supports any type of element, and the array dimensions of each element can be different. But it cannot be initialized by the zeros function, or even do the following:

julia>x = Vector{Matrix{Float64}}(undef, 3)
julia> x[1] = [1 1;1 1];
julia> x[2] = [2 2 2;2 2 2];
julia> x[3] = [3 3 3;3 3 3; 3 3 3];
julia>x
3-element Array{Array{Float64,2},1}:
[1.0 1.0; 1.0 1.0]
[2.0 2.0 2.0; 2.0 2.0 2.0]
[3.0 3.0 3.0; 3.0 3.0 3.0; 3.0 3.0 3.0]
.
julia>zeros(x)
MethodError: no method matching zeros(::Array{Array{Float64,2},1})
Closest candidates are:
zeros(!Matched::Union{Integer, AbstractUnitRange}…) at array.jl:520
zeros(!Matched::Type{T}, !Matched::Union{Integer, AbstractUnitRange}…) where T at array.jl:521
zeros(!Matched::Tuple{Vararg{Union{Integer, AbstractUnitRange},N} where N}) at array.jl:522

Stacktrace:
[1] top-level scope at In[7]:1
[2] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

This approach supports zeros() functions, but does not allow each element to be defined as a different dimension
So , is there any way to support both?

Lets say you have a list of the sizes of each array, then you can use a comprehension:

julia> l = [ (2,2), (3,3), (3,3) ];

julia> m = [ zeros(s) for s in l ]
3-element Array{Array{Float64,2},1}:
 [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 0.0; 0.0 0.0 0.0]
2 Likes

If the arrays don’t all have the same size, then you shouldn’t use StaticArrays (you can, but you will lose the main benefits and it might even be slower because of the type-instability). The point of StaticArrays is to exploit the case where the array size is static (fixed at compile-time).

4 Likes

That’s a good idea! Thank you very much!