# Concatening matrix in a loop

Dear users,
I need to build a matrix using a loop, like this:

``````X = zeros(3,1)
for i=1:10
x = rand(3,1)
X = [X x]
end
``````

i.e., I need to build the columns of X using a looping. What’s the better way to do its?

To be more efficient, preallocate `X` and then fill it. Something like this

``````X = zeros(3,10)
for i = 1:10
X[:,i] = rand(3)
end
``````

(In this particular case, you could do `X=rand(3,10)`.)

2 Likes
``````reduce(hcat, (rand(3) for i in 1:10); init=X)
``````
2 Likes

Also, please don’t post the same thing multiple times.

Because I just couldn’t resist, and as this is something I can see myself using often enough:

``````function func1(;n=10, m=3)
X = zeros(m,1)
for i=1:n
x = rand(m,1)
X = [X x]
end
return  X
end

function func2(;n=10, m=3)
X = zeros(m,n)
for i = 1:n
X[:,i] = rand(m)
end
return X
end

function func3(;n=10, m=3)
X = zeros(m,n)
reduce(hcat, (rand(m) for i in 1:n); init=X)
return X
end

julia> @btime func1(n=10, m=3)
878.317 ns (31 allocations: 3.89 KiB)

julia> @btime func2(n=10, m=3)
502.572 ns (11 allocations: 1.42 KiB)

julia> @btime func3(n=10, m=3)
1.210 μs (32 allocations: 6.33 KiB)

julia> @btime func1(n=100, m=3)
20.901 μs (301 allocations: 148.00 KiB)

julia> @btime func2(n=100, m=3)
4.586 μs (101 allocations: 13.44 KiB)

julia> @btime func3(n=100, m=3)
48.901 μs (302 allocations: 384.52 KiB)

julia> @btime func1(n=10, m=30)
2.589 μs (31 allocations: 20.52 KiB)

julia> @btime func2(n=10, m=30)
1.080 μs (11 allocations: 5.78 KiB)

julia> @btime func3(n=10, m=30)
5.433 μs (32 allocations: 43.92 KiB)
``````

Potential shortcomings in my benchmarking aside, I was not expecting the large differences, especially with the 100 x 3 case.

2 Likes

Note that these 3 functions don’t have quite the same output. And also that `collect`ing the generator makes a big difference:

``````julia> func4(;n, m) = reduce(hcat, rand(m) for i in 1:n);

julia> @btime func4(n=100, m=3);
19.821 μs (301 allocations: 145.44 KiB)

julia> func5(;n, m) = reduce(hcat, [rand(m) for i in 1:n]);

julia> @btime func5(n=100, m=3);
6.063 μs (102 allocations: 14.31 KiB)
``````
1 Like