development

MATLAB에서 n 차원 행렬의 각 요소를 어떻게 반복합니까?

big-blog 2020. 10. 14. 07:59
반응형

MATLAB에서 n 차원 행렬의 각 요소를 어떻게 반복합니까?


문제가 있습니다. 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

선형 인덱스가 더 유용한 상황이 많이 있습니다. 선형 인덱스와 2 차원 (또는 그 이상의) 첨자 간의 변환은 sub2ind 및 ind2sub 함수를 사용하여 수행됩니다.

선형 인덱스는 일반적으로 matlab의 모든 배열에 적용됩니다. 따라서 구조, 셀형 배열 등에 사용할 수 있습니다. 선형 인덱스의 유일한 문제는 너무 커질 때입니다. MATLAB은 32 비트 정수를 사용하여 이러한 인덱스를 저장합니다. 따라서 배열에 총 2 ^ 32 개 이상의 요소가 있으면 선형 인덱스가 실패합니다. 희소 행렬을 자주 사용하는 경우에만 문제가됩니다. 가끔 이로 인해 문제가 발생합니다. (나는 64 비트 MATLAB 릴리스를 사용하지 않지만, 운이 좋은 사람들을 위해 문제가 해결되었다고 생각합니다.)


몇 가지 다른 답변에서 지적했듯이 단일 for 루프 에서 to to 까지 선형 인덱스A사용하여 (모든 차원의) 행렬의 모든 요소를 ​​반복 할 수 있습니다 . 또한 사용할 수있는 몇 가지 기능이 있습니다 : .1numel(A)arrayfuncellfun

먼저 A(라고하는 my_func) 의 각 요소에 적용하려는 함수가 있다고 가정합니다 . 먼저이 함수에 대한 함수 핸들만듭니다 .

fcn = @my_func;

경우 A(두 번 등, 단일 유형의) 임의의 차원의 매트릭스를, 당신은 사용할 수 있습니다 arrayfun적용하는 my_func각 요소 :

outArgs = arrayfun(fcn, A);

경우 AA는 셀 어레이 임의의 차원, 당신은 사용할 수 있습니다 cellfun적용 할 my_func각 셀에 :

outArgs = cellfun(fcn, A);

함수 my_funcA입력 으로 받아 들여야 합니다. 의 출력이 있으면 my_func에 배치 outArgs되며 A.

만약 출력에 한 가지주의 ... my_func다른 크기 및 형태의 반환 출력은 다른 요소에서 동작 할 때 A, 다음 outArgs세포 배열로 만들 수있을 것이다. 이것은 어느 쪽인지를 호출하여 수행됩니다 arrayfun또는 cellfun추가 매개 변수 / 값 쌍 :

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

또 다른 트릭은 ind2subsub2ind. 와 결합 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

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.


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.


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.


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.

참고URL : https://stackoverflow.com/questions/758736/how-do-i-iterate-through-each-element-in-an-n-dimensional-matrix-in-matlab

반응형