Suggestions for manipulating an array

Hey guys and girls

I have this case, where I have a row vector N, which I want to rewrite to a matrix of these forms:

N = [N1 N2 N3 N4]

N2D = [N1 0 N2 0 N3 0 N4 0;
       0 N1 0 N2 0 N3 0 N4];

N3D = [N1 0 0 N2 0 0 N3 0 0 N4 0 0; 0 N1 0 0 N2 0 0 N3 0 0 N4 0 ; 0 0 N1 0 0 N2 0 0 N3 0 0 N4]

Currently I am doing it like this:

Nx     = 8
N2D    =  Array{Basic}(undef, 2, Nx)
N2D[1,2:2:Nx]   = [0 0 0 0]
N2D[2,1:2:Nx-1] = [0 0 0 0]
N2D[1,1:2:Nx-1] = N
N2D[2,2:2:Nx]   = N

In the past I hardcoded a for loop, but maybe there is a way to make a function do this transformation more effeciently.

Kind regards

A for loop should be extremely efficient. If that solution is already working for you, then you’re already done!

Is constructing this matrix actually a performance bottleneck? If so, have you considered not constructing it at all? For example, you could create your own AbstractArray which stores only the non-zero entries and implement Base.getindex(::MyNewArrayType, i) to return the right nonzero entry or zero as appropriate. Or, for that matter, can you just use SparseArrays, which already do exactly that?

A lot of these questions will be easier to answer if you can tell us more about what your performance bottlenecks are and what you’re planning to do with the resulting data structure.

2 Likes

May be you can use this function? I’m not sure what your real situation is though, more information about the context can help.

julia> function build_nD(N,dim)
           out = fill(0,dim,dim*length(N))
           for i = 1:dim
               for j = 1:length(N)
                   out[i,(j-1)dim+i] = N[j]
               end
           end
           out
       end
build_nD (generic function with 1 method)

julia> N = [1 2 3 4];

julia> dim = 5;

julia> build_nD(N,dim)
5×20 Array{Int64,2}:
 1  0  0  0  0  2  0  0  0  0  3  0  0  0  0  4  0  0  0  0
 0  1  0  0  0  0  2  0  0  0  0  3  0  0  0  0  4  0  0  0
 0  0  1  0  0  0  0  2  0  0  0  0  3  0  0  0  0  4  0  0
 0  0  0  1  0  0  0  0  2  0  0  0  0  3  0  0  0  0  4  0
 0  0  0  0  1  0  0  0  0  2  0  0  0  0  3  0  0  0  0  4
1 Like

Hey again, so it isn’t really a performance bottleneck for me, I just enjoy seeing/learning how others will approach a similar problem - sometimes I have experienced that I make a complex and working solution and then some one pops in, and says you can just do this, this and that. Always fun for me to learn more - I will have a look at sparse arrays and trying to define something as you describe.

Kind regards

Thanks, seems close to what I want and much smaller than my own solution - will try to test it later and let you hear back.

Kind regards

Thank you very much for your code bit - I modified it slightly, so that it also determines and preallocates the right type:

function build_nD(N,dim)
    typ = eltype(N)
           out = Array{typ,2}(fill(0,dim,dim*length(N)))
           for i = 1:dim
               for j = 1:length(N)
                   out[i,(j-1)dim+i] = N[j]
               end
           end
           out
       end

This was necessary since I was using SymEngine and symbolic variables cannot be inserted into int/float arrays. It was much more compact than my first for loop, so I am pretty happy with it.

Kind regards

May be this is more readable, you don’t need to specify Array{T,2}:

T = eltype(N)
out = zeros(T, dim,dim*length(N))

Thank! I used that change.