MATLAB Answers

0

Assigning values to an array of arbitrary dimensions in MATLAB.

Asked by Michael Ransom on 16 Mar 2019 at 20:10
Latest activity Edited by per isakson
on 18 Mar 2019 at 2:26
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?

  4 Comments

Show 1 older comment
Thanks for your answer. Apologies if the question wasn't clear. I will try another example.
I am dealing with a problem where dimensionality grows as an integer j increases. So, for the example in the question, there are two vectors and each with length d.
clear;clc;
rng = ('default'); % for reproducing rand; element values aren't important
d = 5; % vector length; arbitrary
v{ 1 } = rand( d , 1 ); % vector 1
v{ 2 } = rand( d , 1 ); % vector 2
The objective is then to perform element-wise multiplication for and as before to obtain the elements in , which in this case is:
for m = 1:d
for n = 1:d
Array( m , n ) = v{ 1 }( m ).*v{ 2 }( n ) ;
end
end
So, there are two index variables, m and n, which indexs the elements of a matrix. Similarly for ,
clear;clc;
rng = ('default'); % for reproducing rand
d = 5; % vector length
v{ 1 } = rand( d , 1 ); % vector 1
v{ 2 } = rand( d , 1 ); % vector 2
v{ 3 } = rand( d , 1 ); % vector 2
for p = 1:d
for q = 1:d
for r = 1:d
Array( p , q , r ) = v{ 1 }( p ).*v{ 2 }( q ).*v{ 3 }( r ) ;
end
end
end
which uses three index variables, and r, which indexs the elements of a matrix.
The problem I have is to be able to this with an arbitrary value of j. Explicitly,
clear;clc;
rng = ('default'); % for reproducing rand
d = 5; % vector length
j = 10; % arbitrary value
for m = 1:j
v{ m } = rand( d , 1 ); % vectors 1,...,j
end
and then perform element-wise multiplication, as above, with each vector to form a array. The problem is I don't know how to perform the indexing required to accompish this, or a better way of producing the same outcome.
The and functions could be a way forward, but I'm not familiar with them. I will have to do some experiments and find out.
I hope this made my question a little clearer.
Thanks for your answer, Walter.
The answer you have commented returns a vector of length d. Unfortunately, it's not what I'm after. Please see the comment to dpb for further information on the problem if you haven't done so already.
However, the function seems useful for element-wise multiplication across the elements of vectors , as does for concatenating results. I think we might be on the right lines.

Sign in to comment.

Products


Release

R2018b

1 Answer

Answer by per isakson
on 17 Mar 2019 at 12:13
Edited by per isakson
on 18 Mar 2019 at 2:26
 Accepted Answer

"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

  2 Comments

Thanks for your answer, per isakson.
This is exactly what I was after. A few rearrangements:
clear; clc;
rng = ('default'); % for reproducing rand
d = 5; % vector length
j = 3; % arbitrary value
v = cell( 1 , j ) ;
for m = 1:j
v{ m } = rand( d , 1 ); % vectors 1,...,j
end
Array = value2arrayND( d , j , v ) ;
followed by the function you provided in your answer with a few tweaks:
function Array = value2arrayND( d , j , v )
Array = NaN.*ones( repmat( d , 1 , j ) );
nel = numel( Array );
sz = size( Array );
dim = cell( 1 , j );
for ii = 1:nel
[dim{:}] = ind2sub( sz, ii );
Array( ii ) = prod( arrayfun( @(jj) v{jj}(dim{jj}), 1:length(v), 'uni',true ) );
end
end
Many thanks!
+1 Per...was thinking on those lines when made initial comment; it came to me overnight precisely how and I was all excited this AM to post my clever solution! Then, you beat me to it! :)

Sign in to comment.