# How do I create a Matrix of Vectors?

Hello everyone!

I’m currently doing the Advent of Code challenges (I’m not asking for help regarding solving it) and for day 4 I’m trying to use an array of vectors.

For the creation I tried `fill(Vector{Int}(), (1000, 1000))` however this copies the result of `Vector{Int}()`
So, whenever I do `push!(arr[y, x], elem)` all positions get `elem` added to them since they’re all the same one.

Is this desired behavior? I understand it works for literal values like `3.14` or `"hello"` however for my use case the only solution I see would be

``````for i in arr
arr[i] = Vector{Int}()
end
``````

Thank you in advance!

1 Like

Consider something like

``````function array_of_empty_vectors(T, dims...)
array = Array{Vector{T}}(undef, dims...)
for i in eachindex(array)
array[i] = Vector{T}()
end
array
end

# this creates a 2x3 matrix with independent Vector{Int}()'s
array_of_empty_vectors(Int, 2, 3)
``````

Also, regading

Yes, `fill` does not create copies, so each element will be the same vector.

``````A =  fill(Vector{Int}(), (1000, 1000));
A .= copy.((Vector{Int}(),));
``````

Or

``````A = [copy(Vector{Int}()) for i in 1:1000, j in 1:1000];
``````

No need for the `copy` here and I’d say that the comprehension is the standard solution. But this is also cute:

``````julia> 0 .|> fill(x->Vector{Int}(), 2, 3)
2×3 Array{Array{Int64,1},2}:
[]  []  []
[]  []  []
``````

Does someone know if this can be done without a dummy input variable?

2 Likes

Slightly shorter solution:

``````[Int[] for i=1:1000, j=1:1000]
``````

You can do `(f->f()).(fill(()->Vector{Int}(),2,3))`, but it’s not that readable. And unlike the comprehension, it needlessly allocates a temporary array of functions.

1 Like

That doesn’t necessarily make a blip in your profile though, unless your matrices are tiny.

``````julia> @btime fill(()->Int[], 1000, 1000);
24.891 ns (1 allocation: 80 bytes)
``````

I kinda like this construction, although there’s still a high amount of magic in it.

``````array_of_empty_vectors(T, dims...) = T .|> fill(T -> T[], dims...)
``````

Can you break down the syntax here?
The whole beginning `0 .|>` is weird for me

What does the `.=` do?
The list comprehension seems more elegant to me, any guidelines on better practices?

Please review the documentation about broadcasting.

I think you need some shape to broadcast on. Another version could be

``````(_ -> Vector{Int}()).(fill(nothing, 2, 3))
``````

where, if you wrap it in a function, I think the compiler is smart enough to ignore the redundant parts. Another option is

``````(T -> Vector{T}()).(fill(Int, 2, 3))
``````

which almost borders on being readable

In short, fill a matrix with copies of an anonymous function that for any input value produces a fresh empty vector. Then transform that matrix into a new matrix by, element for element, running that function with 0 as input. The result is a matrix of empty vectors.

Sorry about that, I had to trick the dot broadcast syntax into doing what I wanted. That’s why I regarded the comprehension as the standard solution.

1 Like