Assign a value for one dimension of multi-dimensional array

Hi, I’m a bit lost with the following simple exercise. I was wondering what would be the most efficient way to achieve this.

Suppose I have zeros(5,3,2), which returns the following.

5×3×2 Array{Float64, 3}:
[:, :, 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

[:, :, 2] =
 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

I want to change the third column of each matrix by its index of the third array likewise :

A = zeros(5,3,2)

5×3×2 Array{Float64, 3}:
[:, :, 1] =
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1

[:, :, 2] =
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2

I wondered if there is a similar syntax to A[any, any,1] .= 1 and if vcat(A[:,:,1],A[:,:,2]) could be a fast way to get the following final result.

 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  1
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2
 0.0  0.0  2

I think a for loop is probably simplest for this.

julia> x = zeros(5,3,2);

julia> for k in axes(x,3)
               x[:,end,k] .= k
       end

julia> x
5×3×2 Array{Float64, 3}:
[:, :, 1] =
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0

[:, :, 2] =
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0

I don’t fully comprehend your last question, but you can achieve your last result using

julia> reduce(vcat,eachslice(x,dims=3))
10×3 Matrix{Float64}:
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0

It seems like it might have been simpler to have used a 2-vector of 5x3 matrices to begin with. Unlike MATLAB, NumPy, and some other platforms, it isn’t necessary to vectorize operations to get fast code when using Julia.

You also could assemble your final matrix directly like

julia> y = zeros(10,3);

julia> for i in axes(y,1)
               y[i,end] = div(i-1,5)+1
       end

julia> y
10×3 Matrix{Float64}:
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
3 Likes

You can construct the first result via the following.

julia> [1,1,1,1,1] .* [0;; 0;; 1] .* [1. ;;; 2]
5×3×2 Array{Float64, 3}:
[:, :, 1] =
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0
 0.0  0.0  1.0

[:, :, 2] =
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0
 0.0  0.0  2.0

Here is another way to construct the second result.

julia> [(I[2]==3)*(1 + (I[1] > 5)) for I in CartesianIndices((10,3))]
10×3 Matrix{Int64}:
 0  0  1
 0  0  1
 0  0  1
 0  0  1
 0  0  1
 0  0  2
 0  0  2
 0  0  2
 0  0  2
 0  0  2
2 Likes

Thank you very much for the suggestion. I didn’t know the usage of ;; and ;;;. It’s awesome!

Thank you very much. It workers slightly faster with your suggested version. I’ll use it.