[arrays] 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

모든 포인트를 확인하려는 경우 벡터화 된 방법만큼 빠르지는 않지만 대부분의 포인트를 평가할 필요가 없다면 시간을 상당히 절약 할 수 있습니다.


답변

이러한 솔루션은 사용하는 것보다 더 빠릅니다 (약 11 %) numel.

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

또는

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

UPD. 마지막 답변에서 감지 된 오류에 대한 tnx @rayryeng


부인 성명

이 게시물이 참조 한 타이밍 정보는 근본적인 오타로 인해 부정확하고 정확하지 않습니다 (아래 댓글 스트림과 편집 기록 참조 -특히이 답변의 첫 번째 버전을 확인하십시오). 경고 Emptor .


답변

의 다른 용도를 더 자세히 살펴보면 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 구문으로 만들면 원하는 것을 할 것이라고 생각합니다.

또한 여기에 설명 된대로 선형 인덱싱을 수행 할 수 있어야합니다 .