我有个问题。我需要遍历 MATLAB 中 n 维矩阵中的每个元素。问题是,我不知道如何对任意数量的维度执行此操作。我知道我可以说
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
等等,但是有没有办法为任意数量的维度做到这一点?
我有个问题。我需要遍历 MATLAB 中 n 维矩阵中的每个元素。问题是,我不知道如何对任意数量的维度执行此操作。我知道我可以说
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
如果您不需要知道 i,j,k, 您所在的位置,这将很有用。但是,如果您不需要知道您所在的索引,您最好使用 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
结果是,我们可以使用单个循环依次访问通用 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
在许多情况下,线性索引更有用。线性索引和二维(或更高)维下标之间的转换是通过 sub2ind 和 ind2sub 函数完成的。
线性索引通常适用于 matlab 中的任何数组。所以你可以在结构、元胞数组等上使用它。线性索引的唯一问题是当它们变得太大时。MATLAB 使用 32 位整数来存储这些索引。因此,如果您的数组中的元素总数超过 2^32 个,则线性索引将失败。如果您经常使用稀疏矩阵,这真的只是一个问题,有时这会导致问题。(虽然我没有使用 64 位的 MATLAB 版本,但我相信那些幸运的人已经解决了这个问题。)
正如在其他一些答案中所指出的,您可以在单个 for 循环中使用从to的线性索引A
迭代矩阵(任何维度)中的所有元素。您还可以使用几个函数:和.1
numel(A)
arrayfun
cellfun
让我们首先假设您有一个要应用于A
(称为my_func
)的每个元素的函数。您首先为此函数创建一个函数句柄:
fcn = @my_func;
如果A
是任意维度的矩阵(双精度、单精度等),您可以使用它arrayfun
来应用于my_func
每个元素:
outArgs = arrayfun(fcn, A);
如果A
是任意维度的单元格数组cellfun
,您可以使用应用于my_func
每个单元格:
outArgs = cellfun(fcn, A);
该函数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);
另一个技巧是使用ind2sub
and sub2ind
。与numel
and结合使用size
,您可以执行以下操作,创建一个 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
您可以使递归函数完成工作
L = size(M)
idx = zeros(L,1)
length(L)
最大深度for idx(depth) = 1:L(depth)
length(L)
,请执行元素操作,否则再次调用该函数depth+1
如果您想检查所有点,不如矢量化方法快,但如果您不需要评估其中的大多数点,它可以节省大量时间。
如果您更深入地研究其他用途,size
您会发现您实际上可以获得每个维度大小的向量。此链接向您显示文档:
www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html
获得大小向量后,迭代该向量。像这样的东西(请原谅我的语法,因为我从大学起就没有使用过 Matlab):
d = size(m);
dims = ndims(m);
for dimNumber = 1:dims
for i = 1:d[dimNumber]
...
把它变成实际的 Matlab 法律语法,我认为它会做你想要的。
此外,您应该能够按照此处所述进行线性索引。
您想模拟 n 嵌套的 for 循环。
遍历n维数组可以看作是增加n位数。
在每个维度上,我们有与维度长度一样多的数字。
例子:
假设我们有数组(矩阵)
int[][][] T=new int[3][4][5];
在“for notation”中,我们有:
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 位数。您可以这样做,您可以从数字的任何值开始,并通过任何数字增加/减少数字。这样,您可以模拟从表中某处开始但不在末尾结束的嵌套 for 循环。
不过,这并不是一件容易的事。不幸的是,我无法使用 matlab 表示法。