如何迭代MATLAB中的n维matrix中的每个元素?

我有个问题。 我需要遍历MATLAB中的一个n维matrix中的每个元素。 问题是,我不知道如何做到这一点的任意数量的维度。 我知道我可以说

for i = 1:size(m,1) for j = 1:size(m,2) for k = 1:size(m,3) 

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

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

 for idx = 1:numel(array) element = array(idx) .... end 

如果你不需要知道我在你身边,那么这很有用。 然而,如果你不需要知道你在哪个索引,你可能更好使用arrayfun()

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 

通过将数组展开成一个向量,我们可以看到元素存储在内存中的顺序。

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

正如你所看到的,第8个元素是数字7.实际上,函数find将其结果作为线性索引返回。

 find(A>6) ans = 1 6 8 

结果是,我们可以使用一个单一的循环依次访问每个元素。 例如,如果我们想要把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 

有很多情况下线性指数更有用。 线性索引与两个(或更高)维度下标之间的转换是通过sub2ind和ind2sub函数完成的。

线性索引一般适用于matlab中的任何数组。 所以你可以在结构,单元arrays等上使用它。线性索引的唯一问题是当它们变得太大时。 MATLAB使用一个32位整数来存储这些索引。 所以如果你的数组中有多于2 ^ 32个元素,线性索引将会失败。 如果你经常使用稀疏matrix,偶尔会导致问题,这实际上只是一个问题。 (尽pipe我没有使用64位的MATLAB版本,但我相信这个问题已经被解决了。

正如在其他一些答案中指出的那样,您可以在单个for循环中使用从1numel(A)的线性索引遍历matrixA (任意维)中的所有元素。 还有一些其他的技巧可以使用: ARRAYFUN和CELLFUN 。

我们首先假设你有一个你想要应用到A的每个元素(称为“my_func”)的函数。 你首先为这个函数创build一个函数句柄 :

 fcn = @my_func; 

如果A是任意维的matrix(types为double,single等),则可以使用ARRAYFUN将“my_func”应用于每个元素:

 outArgs = arrayfun(fcn,A); 

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

 outArgs = cellfun(fcn,A); 

函数“my_func”必须接受A作为input。 如果有来自“my_func”的任何输出,则将这些输出放置在outArgs中 ,这与A的大小/尺寸相同。

一个警告输出…如果“my_func”在A的不同元素上操作时返回不同大小和types的输出,那么outArgs将不得不被制成单元arrays。 这是通过调用ARRAYFUN或CELLFUN与一个额外的参数/值对来完成的:

 outArgs = arrayfun(fcn,A,'UniformOutput',false); outArgs = cellfun(fcn,A,'UniformOutput',false); 

另一个技巧是使用ind2subsub2ind 。 结合numelsize ,这可以让你做类似下面的事情,创build一个N维数组,然后将“对angular线”上的所有元素设置为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 

你可以做一个recursion函数来完成这个工作

  • L = size(M)
  • idx = zeros(L,1)
  • length(L)作为最大深度
  • 循环for idx(depth) = 1:L(depth)
  • 如果您的深度是length(L) ,请执行元素操作,否则以depth+1再次调用函数

如果你想检查所有的点,不如vector化的方法快,但如果你不需要评估其中的大部分点,它可以是一个相当节省时间。

这些解决scheme比使用numel更快(约11%);)

 for idx = reshape(array,1,[]), element = element + idx; end 

要么

 for idx = array(:)', element = element + idx; end 

UPD。 tnx @rayryeng在上次回答中检测到错误


放弃

这篇文章引用的时间信息是不正确的,由于一个基本的拼写错误(请参阅下面的评论stream以及编辑历史 – 特别是看这个答案的第一个版本)不准确。 注意到Emptor 。

如果您深入了解其他size用法,则可以看到实际上可以获得每个维度大小的vector。 此链接显示您的文档:

http://www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html

获得大小vector后,迭代该vector。 像这样的东西(原谅我的语法,因为自从大学以来我没有使用Matlab):

 d = size(m); dims = ndims(m); for dimNumber = 1:dims for i = 1:d[dimNumber] ... 

把它变成真正的Matlab合法语法,我想它会做你想做的。

另外,您应该能够按照此处所述进行线性索引。

你想模拟n-nested for循环。

通过n维数组迭代可以看作增加n位数。

在每一个暗室里,我们都有和暗淡的长度一样多的数字。

例:

假设我们有arrays(matrix)

 int[][][] T=new int[3][4][5]; 

在“为符号”我们有:

 for(int x=0;x<3;x++) for(int y=0;y<4;y++) for(int z=0;z<5;z++) T[x][y][z]=... 

要模拟这个,你将不得不使用“n位数字符号”

我们有3位数字,第一位数字是3位数字,第二位数字是4位数字,第三位数字是5位数字

我们必须增加数量,所以我们会得到序列

 0 0 0 0 0 1 0 0 2 0 0 3 0 0 4 0 1 0 0 1 1 0 1 2 0 1 3 0 1 4 0 2 0 0 2 1 0 2 2 0 2 3 0 2 4 0 3 0 0 3 1 0 3 2 0 3 3 0 3 4 and so on 

所以你可以写代码来增加这样的n位数字。 你可以这样做,你可以从数字的任何值开始,按任意数字增加/减less数字。 这样,您可以模拟嵌套循环,从表中的某处开始,而不是结束。

但这不是一件容易的事情。 我不能帮助matlab符号不幸。