如何迭代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循环中使用从1到numel(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);
另一个技巧是使用ind2sub
和sub2ind
。 结合numel
和size
,这可以让你做类似下面的事情,创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符号不幸。