131 views (last 30 days)

Show older comments

I have a problem that requires assigning values to an array of arbitrary dimensions.

For a given integer j, I pre-allocate a regular j-dimensional array such that

where are integers for . Such an array in MATLAB looks like:

Array = NaN.*ones( repmat( d , 1 , j ) ) ;

The problem is assigning values for elements in this array. Specifically, given are vectors of length , I require all combinations of element-wise multiplication for each of these vectors, where each result is assigned to .

For the simplest case , assuming vectors are stored in cell-arrays, I can do this quite easily using loops:

for m = 1:d

for n = 1:d

Array( m , n ) = v{ 1 }( m ).*v{ 2 }( n ) ;

end

end

But, a "psudeo-code" implementation with j loops would look something like:

for m( 1 ) = 1:d

...

for m( j ) = 1:d

Array( m( 1 ) , ... , m( j ) ) = v{ 1 }( m( j ) ).* ... .*v{ j }( m( j ) ) ;

end

...

end

The indexing of now becomes variable, which I have had no success in implementing.

Does there exist a way of assigning values to an array of arbitrary dimensions in MATLAB in this manner, or perhaps a neater method?

per isakson
on 17 Mar 2019

Edited: per isakson
on 18 Mar 2019

"The problem I have is to be able to this with an arbitrary value of j." I think value2arrayND does that. It takes a cell array, {dim1,dim2,dim3,...}, and returns an array, the size of which is [dim1,dim2,dim3,...]. value2array2D and value2array3D are based on the code of your comment. They are used to produce expected values.

>> a2 = value2array2D( );

>> aN2 = value2arrayND( {5,5} );

>> aN2-a2

ans =

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

>> a3 = value2array3D( );

>> aN3 = value2arrayND( {5,5,5} );

>> aN3(:,:,3)-a3(:,:,3)

ans =

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

where

function array = value2arrayND( d )

rng('default'); % for reproducing rand;

N = length(d);

v = cell( 1, N );

for jj = 1 : N

v{ jj } = rand( d{jj}, 1 );

end

array = nan(d{:});

nel = numel( array );

sz = [d{:}];

dim = cell( 1, N );

for ii = 1 : nel

[dim{:}] = ind2sub( sz, ii );

array(ii) = prod( arrayfun( @(jj) v{jj}(dim{jj}), 1:N, 'uni',true ) );

end

end

and

function array = value2array3D( )

rng('default'); % for reproducing rand;

d = { 5, 5, 5 }; % vector length; arbitrary

v{ 1 } = rand( d{1}, 1 ); % vector 1

v{ 2 } = rand( d{2}, 1 ); % vector 2

v{ 3 } = rand( d{3}, 1 ); % vector 3

array = nan(d{:});

for p = 1 : d{1}

for q = 1 : d{2}

for r = 1 : d{3}

array( p, q, r ) = v{ 1 }( p ).*v{ 2 }( q ).*v{ 3 }( r );

end

end

end

end

and

function array = value2array2D( )

rng('default'); % for reproducing rand;

d = { 5, 5 }; % vector length; arbitrary

v{ 1 } = rand( d{1}, 1 ); % vector 1

v{ 2 } = rand( d{2}, 1 ); % vector 2

array = nan(d{:});

for m = 1 : d{1}

for n = 1 : d{2}

array( m, n ) = v{ 1 }( m ).*v{ 2 }( n );

end

end

end

dpb
on 17 Mar 2019

Christine Tobler
on 17 Jul 2020

Using the somewhat recent implicit expansion, this can also be done without indexing into every element of the array:

function Array = value2arrayND(v)

Array = 1;

for ii=1:length(v)

% Turn d-by-1 vector into 1-by-...-by-1-by-d vector, where d is in dimension ii

viiPermuted = permute(v{ii}(:), [2:ii 1 ii+1:length(v)]);

Array = Array .* viiPermuted;

end

For the 2D case, this corresponds to

Array = v{1}(:) .* v{2}(:).'; % (d-by-1 matrix) .* (1-by-d matrix)

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!