私は問題があります。MATLABのn次元行列のすべての要素を反復処理する必要があります。問題は、任意の数の次元に対してこれを行う方法がわからないことです。私は言うことができることを知っています
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
などですが、任意の数の次元に対してそれを行う方法はありますか?
私は問題があります。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()を使用することをお勧めします。
I = cell(1, ndims(array)); [I{:}] = ind2sub(size(array),idx);
。
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リリースを使用していませんが、使用している幸運な個人の問題は解決されたと思います。)
x = ones(1,2^33,'uint8'); x(2^33)
期待どおりに機能します。
他のいくつかの回答で指摘されているように、単一のforループでからからまでの線形インデックスA
を使用して、(任意の次元の)行列内のすべての要素を反復処理できます。使用できる関数もいくつかあります:と。1
numel(A)
arrayfun
cellfun
まず、A
(と呼ばれるmy_func
)の各要素に適用する関数があると仮定します。まず、この関数への関数ハンドルを作成します。
fcn = @my_func;
場合はA
、任意の寸法の(double型の、単一、など)行列では、使用することができますarrayfun
適用するmy_func
各要素に:
outArgs = arrayfun(fcn, A);
場合A
であるセル配列の任意の次元のは、あなたが使用することができますcellfun
適用するにはmy_func
、各セルに:
outArgs = cellfun(fcn, A);
関数my_func
はA
入力として受け入れる必要があります。からの出力がある場合my_func
、これらはに配置されますoutArgs
。これは、と同じサイズ/寸法になりA
ます。
場合は出力に1つの警告は...my_func
さまざまなサイズと種類のリターン出力は、それが別の要素に動作している場合A
は、outArgs
セル配列に行う必要があります。これは、いずれarrayfun
かcellfun
を呼び出すか、追加のパラメーター/値のペアを使用して実行されます。
outArgs = arrayfun(fcn, A, 'UniformOutput', false);
outArgs = cellfun(fcn, A, 'UniformOutput', false);
もう一つのトリックは使用することです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
すべてのポイントをチェックしたい場合はベクトル化されたメソッドほど速くはありませんが、それらのほとんどを評価する必要がない場合は、かなりの時間を節約できます。
1 : array(:)
と同等1 : array(1)
です。これはすべての要素を反復するわけではないため、実行時間が速くなります。さらに、浮動小数点数をrand
生成します。これを行うと、ステートメントが初期値が1で、終了値が1以外の範囲の浮動小数点数である増加ベクトルを見つけようとしているため、空の配列が生成されます。1.のステップ。そのような可能なベクトルはなく、結果として空のベクトルになります。あなたのループは実行されないので、あなたの主張は誤りです。-1票。ごめんなさい。1 : array(:)
[0,1)
for
reshape(...)
です。
1 : array(:)
作成後、コマンドプロンプトにonと入力しますarray
。空行列を取得しますか?はいの場合、コードは機能しません。あなたが虚偽の情報を提供しているので、私は投票を辞めます。
他の用途を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構文にすると、あなたが望むことを実行できると思います。
n-nestedforループをシミュレートしたいとします。
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桁の数字があり、1桁目は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桁の数字を増やすためのコードを書くことができます。数値の任意の値から開始して、任意の数値で桁を増減できるようにすることができます。このようにして、テーブルのどこかで始まり、最後ではなく終了するネストされたforループをシミュレートできます。
ただし、これは簡単な作業ではありません。残念ながら、MATLAB表記は手伝うことができません。