How to loop through an unknown number of matrix dimensions?

45 Ansichten (letzte 30 Tage)
KAE am 6 Mär. 2018
Bearbeitet: KAE am 8 Aug. 2019
I would like to loop through all dimensions of a n-dimensional matrix, but the matrix dimensions are unknown beforehand. Below is an example of generating a matrix of unknown dimensions, if it was a 2D matrix looping over those 2 dimensions. But in fact it could have 1-5 dimensions. Can you think of a good solution?
inputMatrixOfUnknownSize = ones(factor(round(rand(1)*500))); % Example matrix that could have 1 to many dimensions
dimList = size(inputMatrixOfUnknownSize) % List the dimensions
% If it was 2D, here's how we'd loop over those two dimensions...but it isn't necessarily 2D!
for iDim1 = 1:dimList(1)
for iDim2 = 1:dimList(2)
% Operate on each element. In reality the operation will not be the same for all dimensions.
outputMatrixOfUnknownSize(iDim1,iDim2) = outputMatrixOfUnknownSize(iDim1,iDim2)^2;
In my real code, the operation that is performed on each matrix element will depend on the dimension size, so I can't eliminate the loop in the example above.

Akzeptierte Antwort

Jan am 6 Mär. 2018
Bearbeitet: Jan am 28 Feb. 2019
You can use linear indexing, if you want to operate on all elements:
X = rand(2,3,4);
Y = zeros(size(X));
for k = 1:numel(X)
Y(k) = X(k) ^ 2;
Of course Y = X .^ 2 would be easier without a loop, but this is thought as demonstration only.
If you want to operate on submatrices, you can move them to the first dimensions temporarily:
X = rand(2,3,4,5,6);
operateOn = [3,5]; % Operate on submatrix along 3rd and 5th dimension
v = 1:ndims(X);
XX = permute(X, [operateOn, setdiff(v, operateOn)]);
sXX = size(XX);
XX = reshape(XX, [sXX(1:2), prod(sXX(3:end)]);
for k = 1:size(XX, 3)
submatrix = XX(:, :, k);
... do what you want
Another example is using a cell vector for indexing. If you want a subarray with indexing the the last two dimensions - independent from knowing how many dimensions the input has:
X = rand(2,3,4,5,6);
n = ndims(X);
index = cell(1, n);
index(:) = {':'};
index{end-1} = 3;
index{end} = 4;
Y = X(index{:}); % Equivalent to: X(:, :, :, 3, 4)
You can replace a bunch of nested loops by a single loop also using an index vector instead of scalar indices, see Answers: 333926-recursive-function-for-replacing-multiple-for-loops :
X = rand(2,3,4,5,6);
nv = ndims(X);
v = ones(1, nv);
vLim = size(X);
ready = false;
while ~ready
% Do what you need with X and the index vector v
% Update the index vector:
ready = true; % Assume that the WHILE loop is ready
for k = 1:nv
v(k) = v(k) + 1;
if v(k) <= vLim(k)
ready = false; % No, WHILE loop is not ready now
break; % v(k) increased successfully, leave "for k" loop
v(k) = 1; % Reset v(k), proceed to next k
This is equivalent to the following without the need to know the number of dimensions before:
for i1 = 1:size(X, 1)
for i2 = 1:size(X, 2)
for i3 = 1:size(X, 3)
for i4 = 1:size(X, 4)
for i5 = 1:size(X, 5)
v = [i1, i2, i3, i4, i5];
% Do what you need with X and the index vector v

Weitere Antworten (0)


Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by