如何在 MATLAB 中迭代 n 维矩阵中的每个元素?

发布于 2024-07-17 00:32:03 字数 212 浏览 4 评论 0 原文

我有个问题。 我需要在 MATLAB 中迭代 n 维矩阵中的每个元素。 问题是,我不知道如何对任意数量的维度执行此操作。 我知道我可以

for i = 1:size(m,1)
    for j = 1:size(m,2)
        for k = 1:size(m,3)

这么说,但是有没有办法对任意数量的维度做到这一点?

I have a problem. I need to iterate through every element in an n-dimensional matrix in MATLAB. The problem is, I don't know how to do this for an arbitrary number of dimensions. I know I can say

for i = 1:size(m,1)
    for j = 1:size(m,2)
        for k = 1:size(m,3)

and so on, but is there a way to do it for an arbitrary number of dimensions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

鸠魁 2024-07-24 00:32:04

另一个技巧是使用 ind2subsub2ind。 与 numelsize 结合使用,这可以让您执行如下操作,创建一个 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

One other trick is to use ind2sub and sub2ind. In conjunction with numel and size, this can let you do stuff like the following, which creates an N-dimensional array, and then sets all the elements on the "diagonal" to be 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
冰雪之触 2024-07-24 00:32:04

您可以让递归函数完成这项工作

  • Let L = size(M)
  • Let idx = Zeros(L,1)
  • Take length(L) 作为最大深度
  • 循环for idx(深度) = 1:L(深度)
  • 如果你的深度是length(L),则执行元素操作,否则调用该函数再次使用深度+1,

如果您想检查所有点,则速度不如矢量化方法,但如果您不需要评估其中的大多数点,那么它可以节省大量时间。

You could make a recursive function do the work

  • Let L = size(M)
  • Let idx = zeros(L,1)
  • Take length(L) as the maximum depth
  • Loop for idx(depth) = 1:L(depth)
  • If your depth is length(L), do the element operation, else call the function again with depth+1

Not as fast as vectorized methods if you want to check all the points, but if you don't need to evaluate most of them it can be quite a time saver.

秋意浓 2024-07-24 00:32:04

更快(约 11%)

for idx = reshape(array,1,[]),
     element = element + idx;
end

这些解决方案比使用 numel;)或

for idx = array(:)',
    element = element + idx;
end

UPD 。 tnx @rayryeng 检测到上一个答案中的错误


免责声明

由于存在基本的拼写错误,本文引用的计时信息不正确且不准确(请参阅下面的评论流以及 编辑历史记录 - 特别查看此答案的第一个版本)。 买者自负

these solutions are more faster (about 11%) than using numel;)

for idx = reshape(array,1,[]),
     element = element + idx;
end

or

for idx = array(:)',
    element = element + idx;
end

UPD. tnx @rayryeng for detected error in last answer


Disclaimer

The timing information that this post has referenced is incorrect and inaccurate due to a fundamental typo that was made (see comments stream below as well as the edit history - specifically look at the first version of this answer). Caveat Emptor.

猫弦 2024-07-24 00:32:04

如果您深入研究 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 合法语法,我认为它会做你想要的。

此外,您应该能够按照此处。

If you look deeper into the other uses of size you can see that you can actually get a vector of the size of each dimension. This link shows you the documentation:

www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html

After getting the size vector, iterate over that vector. Something like this (pardon my syntax since I have not used Matlab since college):

d = size(m);
dims = ndims(m);
for dimNumber = 1:dims
   for i = 1:d[dimNumber]
      ...

Make this into actual Matlab-legal syntax, and I think it would do what you want.

Also, you should be able to do Linear Indexing as described here.

幻想少年梦 2024-07-24 00:32:04

您想要模拟 n 嵌套的 for 循环。

迭代 n 维数组可以看作是增加 n 位数字。

在每个维度上,我们有与维度长度一样多的数字。

示例:

有数组(矩阵)

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 符号。

You want to simulate n-nested for loops.

Iterating through n-dimmensional array can be seen as increasing the n-digit number.

At each dimmension we have as many digits as the lenght of the dimmension.

Example:

Suppose we had array(matrix)

int[][][] T=new int[3][4][5];

in "for notation" we have:

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]=...

to simulate this you would have to use the "n-digit number notation"

We have 3 digit number, with 3 digits for first, 4 for second and five for third digit

We have to increase the number, so we would get the sequence

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

So you can write the code for increasing such n-digit number. You can do it in such way that you can start with any value of the number and increase/decrease the digits by any numbers. That way you can simulate nested for loops that begin somewhere in the table and finish not at the end.

This is not an easy task though. I can't help with the matlab notation unfortunaly.

策马西风 2024-07-24 00:32:03

您可以使用线性索引来访问每个元素。

for idx = 1:numel(array)
    element = array(idx)
    ....
end

如果您不需要知道您所在的 i、j、k,这非常有用。 但是,如果您不需要知道自己所在的索引,那么最好使用 arrayfun()

You can use linear indexing to access each element.

for idx = 1:numel(array)
    element = array(idx)
    ....
end

This is useful if you don't need to know what i,j,k, you are at. However, if you don't need to know what index you are at, you are probably better off using arrayfun()

独孤求败 2024-07-24 00:32:03

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 版本,但我相信对于那些使用 64 位 MATLAB 版本的幸运者来说,这个问题已经得到解决。)

The idea of a linear index for arrays in matlab is an important one. An array in MATLAB is really just a vector of elements, strung out in memory. MATLAB allows you to use either a row and column index, or a single linear index. For example,

A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2

A(2,3)
ans =
     7

A(8)
ans =
     7

We can see the order the elements are stored in memory by unrolling the array into a vector.

A(:)
ans =
     8
     3
     4
     1
     5
     9
     6
     7
     2

As you can see, the 8th element is the number 7. In fact, the function find returns its results as a linear index.

find(A>6)
ans =
     1
     6
     8

The result is, we can access each element in turn of a general n-d array using a single loop. For example, if we wanted to square the elements of A (yes, I know there are better ways to do this), one might do this:

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

There are many circumstances where the linear index is more useful. Conversion between the linear index and two (or higher) dimensional subscripts is accomplished with the sub2ind and ind2sub functions.

The linear index applies in general to any array in matlab. So you can use it on structures, cell arrays, etc. The only problem with the linear index is when they get too large. MATLAB uses a 32 bit integer to store these indexes. So if your array has more then a total of 2^32 elements in it, the linear index will fail. It is really only an issue if you use sparse matrices often, when occasionally this will cause a problem. (Though I don't use a 64 bit MATLAB release, I believe that problem has been resolved for those lucky individuals who do.)

回忆凄美了谁 2024-07-24 00:32:03

正如其他一些答案所指出的,您可以使用 1numel(A) 的线性索引单个 for 循环。 您还可以使用几个函数: arrayfuncellfun

首先假设您有一个要应用于 A 的每个元素的函数(称为 my_func)。 您首先为此创建一个函数句柄函数:

fcn = @my_func;

如果A是任意维度的矩阵(double、single等类型),则可以使用arrayfunmy_func应用到每个元素:

outArgs = arrayfun(fcn, A);

如果 A元胞数组 为任意维度,您可以使用 cellfunmy_func 应用于每个单元:

outArgs = cellfun(fcn, A);

函数 my_func 必须接受 A 作为输入。 如果 my_func 有任何输出,这些输出将被放置在 outArgs 中,其大小/维度与 A 相同。

关于输出的一个警告...如果 my_func 在对 A 的不同元素进行操作时返回不同大小和类型的输出,则 outArgs 将具有制作成元胞数组。 这是通过使用附加参数/值对调用 arrayfuncellfun 来完成的:

outArgs = arrayfun(fcn, A, 'UniformOutput', false);
outArgs = cellfun(fcn, A, 'UniformOutput', false);

As pointed out in a few other answers, you can iterate over all elements in a matrix A (of any dimension) using a linear index from 1 to numel(A) in a single for loop. There are also a couple of functions you can use: arrayfun and cellfun.

Let's first assume you have a function that you want to apply to each element of A (called my_func). You first create a function handle to this function:

fcn = @my_func;

If A is a matrix (of type double, single, etc.) of arbitrary dimension, you can use arrayfun to apply my_func to each element:

outArgs = arrayfun(fcn, A);

If A is a cell array of arbitrary dimension, you can use cellfun to apply my_func to each cell:

outArgs = cellfun(fcn, A);

The function my_func has to accept A as an input. If there are any outputs from my_func, these are placed in outArgs, which will be the same size/dimension as A.

One caveat on outputs... if my_func returns outputs of different sizes and types when it operates on different elements of A, then outArgs will have to be made into a cell array. This is done by calling either arrayfun or cellfun with an additional parameter/value pair:

outArgs = arrayfun(fcn, A, 'UniformOutput', false);
outArgs = cellfun(fcn, A, 'UniformOutput', false);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文