[arrays] MATLABのn次元行列の各要素をどのように反復するのですか?


Answers

MATLABの配列の線形インデックスの考え方は重要です。 MATLABの配列は、実際にはメモリ内に配置された要素のベクトルです。 MATLABでは、行インデックスと列インデックス、または1つの線形インデックスを使用できます。 例えば、

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リリースを使用していませんが、その幸運な人には問題は解決されていると私は信じています)。

Question

私は問題があります。 私は、MATLABのn次元行列のすべての要素を繰り返し処理する必要があります。 問題は、任意の次元数に対してこれを行う方法がわかりません。 私は言うことができる知っている

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

何かの次元でそれを行う方法はありますか?




ループのn-nestedをシミュレートする必要があります。

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桁、2番目は4桁、3桁目は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桁の数字を増やすコードを書くことができます。 あなたは数字の任意の値で始めることができ、任意の数で数字を増減するような方法でそれを行うことができます。 そうすれば、テーブルのどこかで始まり最後で終わらないループのネストをシミュレートすることができます。

しかし、これは簡単な作業ではありません。 私はmatlab表記法を不幸にすることはできません。




これらのソリューションは、 numelを使用するよりも高速です(約11%)。

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

または

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

UPD。 最後の答えで検出されたエラーの場合はtyx @rayryeng

免責事項

この投稿が参照しているタイミング情報は、基本的なタイプミスが原因で間違っていて不正確です(下記のコメントストリームと編集履歴を参照してください - 特にこの回答の最初のバージョンを見てください)。 警告欄




もう1つのトリックはind2subsub2indを使うことsub2indnumelsizenumelことで、次のようなことができます。これは、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





Links