我有个问题。我需要遍历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)
等等,但是有没有办法针对任意数量的尺寸呢?
Answers:
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版本,但我相信对于那些幸运的人来说,问题已经解决了。)
x = ones(1,2^33,'uint8'); x(2^33)
按预期工作。
正如在其他一些答案中指出的那样,您可以在单个for循环中A
使用线性索引从1
to遍历矩阵(任意维度)中的所有元素numel(A)
。您还可以使用几个功能: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
你可以做一个递归函数
L = size(M)
idx = zeros(L,1)
length(L)
最大深度为准for idx(depth) = 1:L(depth)
length(L)
,请执行元素操作,否则使用再次调用该函数depth+1
如果要检查所有要点,则没有向量化方法快,但是如果不需要评估大多数要点,则可以节省大量时间。
1 : array(:)
等价于1 : array(1)
。这并不会遍历所有元素,这就是运行时间快的原因。此外,rand
生成浮点数,这样做1 : array(:)
会产生一个空数组,因为您的语句试图查找一个初始值为1且终点值为浮点数且不包含1的递增向量[0,1)
。 1.的步骤。没有这样的可能向量,从而导致空向量。您的for
循环无法运行,因此您的声明是错误的。-1票。抱歉。
reshape(...)
。
1 : array(:)
创建完成后,在命令提示符下键入on array
。你得到一个空矩阵吗?如果是,则您的代码不起作用。我离开我的投票,因为您提供的是虚假信息。
如果您进一步了解的其他用途,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-legal语法,我认为它将满足您的要求。
另外,您应该能够按照此处所述进行线性索引。
您要模拟n嵌套for循环。
遍历n维数组可以看作是增加n位数字。
在每个维度上,我们拥有的数字与维度的长度一样多。
例:
假设我们有array(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位数字的代码。您可以以任何数字值开头并以任意数字增加/减少数字的方式进行操作。这样,您可以模拟嵌套的for循环,这些循环从表中的某处开始,直到结束为止。
但是,这并不是一件容易的事。不幸的是,我不禁会用matlab表示法。