私は問題があります。 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
その結果、単一のループを使用して、一般的なn-d配列の各要素に順番にアクセスできます。たとえば、Aの要素を2乗したい場合(はい、これを行うより良い方法があることを知っています)、これを行うことができます。
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ループで 線形インデックス from 1
からnumel(A)
を使用して、(任意の次元の)マトリックスA
のすべての要素を反復処理できます。使用できる関数もいくつかあります: arrayfun
および cellfun
。
最初に、A
の各要素(my_func
と呼ばれる)に適用する関数があると仮定します。まず、この関数に 関数ハンドル を作成します。
fcn = @my_func;
A
が任意の次元の行列(double、singleなど)の場合、arrayfun
を使用して各要素にmy_func
を適用できます。
outArgs = arrayfun(fcn, A);
A
が任意の次元の セル配列 である場合、cellfun
を使用してmy_func
を各セルに適用できます。
outArgs = cellfun(fcn, A);
関数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);
もう1つのトリックは、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
あなたは再帰関数に仕事をさせることができます
L = size(M)
idx = zeros(L,1)
length(L)
を最大深度としますfor idx(depth) = 1:L(depth)
length(L)
の場合、要素操作を実行し、そうでない場合はdepth+1
を使用して関数を再度呼び出しますすべてのポイントをチェックする場合、ベクトル化されたメソッドほど高速ではありませんが、ほとんどのポイントを評価する必要がない場合は、かなり時間を節約できます。