我有一个问题。我需要在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() 可能更好。
I = cell(1, ndims(array)); [I{:}] = ind2sub(size(array),idx);
。 - knedlseppA = 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
结果是,我们可以使用单个循环依次访问一般的n维数组中的每个元素。例如,如果我们想要对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版本,但我相信对于那些幸运的人来说,该问题已得到解决。)
x = ones(1,2^33,'uint8'); x(2^33)
会按预期工作。 - Edric正如其他答案中所指出的那样,您可以使用矩阵 A
(任意维度)中的线性索引从1
到numel(A)
在单个for循环中迭代所有元素。还有一些函数可以使用:arrayfun
和cellfun
。
首先假设您有一个要应用于A
每个元素的函数(称为my_func
)。您首先创建一个函数句柄以引用此函数:
fcn = @my_func;
A
是任意维度的矩阵(类型为double、single等),您可以使用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
和 sub2ind
。结合 numel
和 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
1:array(:)
等同于1:array(1)
。这不会遍历所有元素,这就是为什么您的运行时间很快的原因。此外,rand
生成浮点数,因此执行1:array(:)
将产生一个空数组,因为您的语句试图找到一个初始值为1,结束值为0到1之间的浮点数(选择顶端的数字),以递增的步长1递增的递增向量。不存在这样的可能向量,导致一个空向量。您的for
循环不会运行,所以您的声明是错误的。-1票。抱歉。 - rayryengreshape(...)
。 - mathcowarray
后,在您的命令提示符中键入1:array(:)
。您得到了一个空矩阵吗?如果是,则您的代码无法正常工作。我留下我的投票,因为您提供了错误的信息。 - rayryeng你可以使用递归函数来完成这项工作
L = size(M)
idx = zeros(L,1)
length(L)
视为最大深度for idx(depth) = 1:L(depth)
length(L)
,则进行元素操作,否则使用 depth+1
再次调用该函数如果你不需要评估大部分点,那么它可以节省很多时间,但如果你想检查所有点,它不如矢量化方法快。
你想模拟n层嵌套的for循环。
遍历n维数组可以看作是增加n位数字。
在每个维度上,我们有与该维度长度相同的数字。
例如:
假设我们有一个数组(矩阵)
int[][][] T=new int[3][4][5];
在“for循环符号”中,我们有:
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个数字,第二位有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符号问题。
如果你深入了解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合法语法,我认为它会做你想要的。
另外,你应该能够像这里描述的那样进行线性索引。