23

struct配列arrがあり、各要素には、と呼ばれるものを含む一連のフィールドがあるとしvalます。val次のように、各要素のフィールドを一定の量だけインクリメントしたいと思います。

for i = 1:length(arr)
    arr(i).val = arr(i).val + 3;
end

これは明らかに機能しますが、1行のコードでこれを行う方法があるはずです(forループはありません)。私が思いついた最高のものは2行で、一時変数が必要です。

newVals = num2cell([arr.val] + 3);
[arr.val] = deal(newVals{:});

何か案は?ありがとう。

4

4 に答える 4

13

注意点として、dealここでは必要ありません。

[arr.val] = newVals{:}; % achieves the same as deal(newVals{:})

(foorループなしで)これを行う方法を私が知っている他の唯一の方法はarrayfun、配列内の各構造体を反復処理するために使用することです。

% make a struct array
arr = [ struct('val',0,'id',1), struct('val',0,'id',2), struct('val',0,'id',3) ]

% some attempts
[arr.val]=arr.val; % fine
[arr.val]=arr.val+3; % NOT fine :(

% works !
arr2 = arrayfun(@(s) setfield(s,'val',s.val+3),arr)

その最後のコマンドは、の各構造体をループし、に設定されているarr新しい構造体を返します。s.vals.val=3

ただし、これは、インプレースで動作するのではなく、のコピーを返すため、以前の2ライナーとforループよりも実際には効率が悪いと思います。arr

(Matlabがのような階層化されたインデックス作成をサポートしていないのは残念です[arr.val]=num2cell([arr.val]+3){:})。

于 2012-02-16T00:43:24.803 に答える
2

私はCarlとmathically.coffeeのオリジナルのアイデアが好きです。表現する類似の行が複数あるので、メインラインコードを簡潔にするために、先に進んで汎用サブ関数を作成しました

function varargout = clist(in)
varargout = {in{:}};
end

そうすれば、そのような各行をかなり読みやすい方法で表現できます。

[arr.var]  = clist(num2cell([arr.var]+3));  
[arr.var2] = clist(num2cell([arr2.var]/5+33));  
于 2020-10-27T22:30:04.693 に答える
1

その構造体のすべてのフィールドはスカラーですか、それとも同じサイズですか?その場合、これを行う慣用的なMatlabの方法は、フィールドにスカラー値を持つ構造体の配列ではなく、各フィールドに配列を持つスカラー構造体になるように構造体を再配置することです。次に、のように、フィールドに対してベクトル化された操作を実行できますarr.val = arr.val + 3;。データを再配置できるかどうかを確認してください。この方法で行うと、時間とメモリの両方ではるかに効率的です。おそらく、Matlabが構造体の配列のフィールドを操作するための便利な構文を提供していないのはそのためです。

于 2012-02-16T01:40:00.620 に答える
0

設定しようとしている構造体配列がグラフィックスオブジェクトのセット(ラインハンドル、フィギュアハンドル、軸ハンドルなど)である場合は、次の関数を使用する必要がありますset

x = (1:10)';
Y = rand(10,5);
l = plot(x,Y,'-k'); % returns an array of line handles in l
set(l,'Color','r'); % sets the property 'Color' for all the five lines in l
于 2017-01-27T19:43:05.057 に答える