rlb*_*ond 80 arrays iteration matlab matrix multidimensional-array
我有个问题.我需要在MATLAB中遍历n维矩阵中的每个元素.问题是,我不知道如何为任意数量的维度做这件事.我知道我可以说
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
Run Code Online (Sandbox Code Playgroud)
等等,但有没有办法为任意数量的维度做到这一点?
小智 90
您可以使用线性索引来访问每个元素.
for idx = 1:numel(array)
element = array(idx)
....
end
Run Code Online (Sandbox Code Playgroud)
如果你不需要知道你是什么i,j,k,那么这很有用.但是,如果您不需要知道自己的索引,那么最好使用arrayfun()
小智 33
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
Run Code Online (Sandbox Code Playgroud)
我们可以通过将数组展开到向量中来查看元素存储在内存中的顺序.
A(:)
ans =
8
3
4
1
5
9
6
7
2
Run Code Online (Sandbox Code Playgroud)
如您所见,第8个元素是数字7.事实上,函数find将其结果作为线性索引返回.
find(A>6)
ans =
1
6
8
Run Code Online (Sandbox Code Playgroud)
结果是,我们可以使用单个循环依次访问一般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
Run Code Online (Sandbox Code Playgroud)
在许多情况下,线性索引更有用.使用sub2ind和ind2sub函数完成线性索引和两个(或更高)维度下标之间的转换.
线性索引通常适用于matlab中的任何数组.所以你可以在结构,单元格数组等上使用它.线性索引的唯一问题是当它们变得太大时.MATLAB使用32位整数来存储这些索引.因此,如果您的数组中包含的元素总数超过2 ^ 32个元素,则线性索引将失败.如果你经常使用稀疏矩阵,这实际上只是一个问题,偶尔会导致问题.(虽然我没有使用64位MATLAB版本,但我相信那些幸运的人已经解决了这个问题.)
gno*_*ice 15
正如在其他一些答案中所指出的,您可以使用单个for循环中从1到numericl(A)的线性索引迭代矩阵A(任何维度)中的所有元素.你可以使用其他一些技巧:ARRAYFUN和CELLFUN.
让我们首先假设您有一个要应用于A的每个元素的函数(称为"my_func").首先为此函数创建一个函数句柄:
fcn = @my_func;
Run Code Online (Sandbox Code Playgroud)
如果A是任意维度的矩阵(类型为double,single等),则可以使用ARRAYFUN将"my_func"应用于每个元素:
outArgs = arrayfun(fcn, A);
Run Code Online (Sandbox Code Playgroud)
如果A是任意维度的单元格数组,则可以使用CELLFUN将"my_func"应用于每个单元格:
outArgs = cellfun(fcn, A);
Run Code Online (Sandbox Code Playgroud)
函数"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);
Run Code Online (Sandbox Code Playgroud)
Edr*_*ric 13
另一个技巧是使用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
Run Code Online (Sandbox Code Playgroud)