如何在MATLAB中迭代n维矩阵中的每个元素?

rlb*_*ond 80 arrays iteration matlab matrix multidimensional-array

我有个问题.我需要在MATLAB中遍历n维矩阵中的每个元素.问题是,我不知道如何为任意数量的维度做这件事.我知道我可以说

for i = 1:size(m,1)
    for j = 1:size(m,2)
        for k = 1:size(m,3)
Run Code Online (Sandbox Code Playgroud)

等等,但有没有办法为任意数量的维度做到这一点?

小智 90

您可以使用线性索引来访问每个元素.

for idx = 1:numel(array)
    element = array(idx)
    ....
end
Run Code Online (Sandbox Code Playgroud)

如果你不需要知道你是什么i,j,k,那么这很有用.但是,如果您不需要知道自己的索引,那么最好使用arrayfun()


小智 33

matlab中数组的线性索引的想法是一个重要的.MATLAB中的数组实际上只是元素的向量,在内存中排列.MATLAB允许您使用行索引和列索引,或单个线性索引.例如,

A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2

A(2,3)
ans =
     7

A(8)
ans =
     7
Run Code Online (Sandbox Code Playgroud)

我们可以通过将数组展开到向量中来查看元素存储在内存中的顺序.

A(:)
ans =
     8
     3
     4
     1
     5
     9
     6
     7
     2
Run Code Online (Sandbox Code Playgroud)

如您所见,第8个元素是数字7.事实上,函数find将其结果作为线性索引返回.

find(A>6)
ans =
     1
     6
     8
Run Code Online (Sandbox Code Playgroud)

结果是,我们可以使用单个循环依次访问一般nd数组的每个元素.例如,如果我们想要对A的元素进行平方(是的,我知道有更好的方法可以做到这一点),可以这样做:

B = zeros(size(A));
for i = 1:numel(A)
  B(i) = A(i).^2;
end

B
B =
    64     1    36
     9    25    49
    16    81     4
Run Code Online (Sandbox Code Playgroud)

在许多情况下,线性索引更有用.使用sub2ind和ind2sub函数完成线性索引和两个(或更高)维度下标之间的转换.

线性索引通常适用于matlab中的任何数组.所以你可以在结构,单元格数组等上使用它.线性索引的唯一问题是当它们变得太大时.MATLAB使用32位整数来存储这些索引.因此,如果您的数组中包含的元素总数超过2 ^ 32个元素,则线性索引将失败.如果你经常使用稀疏矩阵,这实际上只是一个问题,偶尔会导致问题.(虽然我没有使用64位MATLAB版本,但我相信那些幸运的人已经解决了这个问题.)


gno*_*ice 15

正如在其他一些答案中所指出的,您可以使用单个for循环中从1numericl(A)的线性索引迭代矩阵A(任何维度)中的所有元素.你可以使用其他一些技巧:ARRAYFUNCELLFUN.

让我们首先假设您有一个要应用于A的每个元素的函数(称为"my_func").首先为此函数创建一个函数句柄:

fcn = @my_func;
Run Code Online (Sandbox Code Playgroud)

如果A是任意维度的矩阵(类型为double,single等),则可以使用ARRAYFUN将"my_func"应用于每个元素:

outArgs = arrayfun(fcn, A);
Run Code Online (Sandbox Code Playgroud)

如果A是任意维度的单元格数组,则可以使用CELLFUN将"my_func"应用于每个单元格:

outArgs = cellfun(fcn, A);
Run Code Online (Sandbox Code Playgroud)

函数"my_func"必须接受A作为输入.如果"my_func"中有任何输出,则这些输出放在outArgs中,其大小/尺寸与A相同.

关于输出的一个警告......如果"my_func"在对A的不同元素进行操作时返回不同大小和类型的输出,则outArgs将必须被制作为单元格数组.这是通过使用附加参数/值对调用ARRAYFUN或CELLFUN来完成的:

outArgs = arrayfun(fcn, A, 'UniformOutput', false);
outArgs = cellfun(fcn, A, 'UniformOutput', false);
Run Code Online (Sandbox Code Playgroud)


Edr*_*ric 13

另一个技巧是使用ind2subsub2ind.会同numelsize,这可以让你做的东西一样下文中,这产生一个N维阵列,然后设置在"对角线"所有元素为1.

d = zeros( 3, 4, 5, 6 ); % Let's pretend this is a user input
nel = numel( d );
sz = size( d );
szargs = cell( 1, ndims( d ) ); % We'll use this with ind2sub in the loop
for ii=1:nel
    [ szargs{:} ] = ind2sub( sz, ii ); % Convert linear index back to subscripts
    if all( [szargs{2:end}] == szargs{1} ) % On the diagonal?
        d( ii ) = 1;
    end
end
Run Code Online (Sandbox Code Playgroud)