web-dev-qa-db-ja.com

構造体フィールドに動的にアクセスするにはどうすればよいですか?

長さの異なるベクトルである多くのフィールドを持つ構造があります。ループ内のフィールドに順番にアクセスしたいと思います。次のようにgetfieldを試しましたが、MATLABはそれを好みません。これどうやってするの?

S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for loopIndex = 1:2
  field = getfield(S, SNames(loopIndex));
  %do stuff w/ field
end
??? Index exceeds matrix dimensions

配列は異なるフィールド長で問題が発生するため、そもそも構造体を使用しています。それに代わるより良い方法はありますか?

31
marciovm

stuffを定義する行に見られるように、括弧内に文字列を置く動的フィールド参照を試してください。

S = struct('A', [1 2], 'B',[3 4 5]); 
SNames = fieldnames(S); 
for loopIndex = 1:numel(SNames) 
    stuff = S.(SNames{loopIndex})
end 

私はスティーブとアダムに同意します。セルを使用します。しかし、この構文は他の状況にいる人に適しています!

43
MatlabDoug

ここで3つのポイントを作成します。

  • 上記のコードでエラーが発生する理由は、SNamesのインデックス付け方法が原因です。関数 fieldnames は文字列の セル配列 を返すため、 content indexing (つまり、中括弧)文字列値にアクセスします。コードの4行目を次のように変更した場合:

    field = getfield(S, SNames{loopIndex});
    

    コードはエラーなく動作するはずです。

  • MatlabDoug で示唆されているように、 動的フィールド名 を使用して getfield を使用する必要を回避できます私の考えでは)。

  • Adamからの提案 構造の代わりに セル配列 を使用することは重要です。これは一般に、長さが異なる一連の配列を単一の変数に収集するための最良の方法です。コードは次のようになります。

    S = {[1 2], [3 4 5]};        % Create the cell array
    for loopIndex = 1:numel(S)   % Loop over the number of cells
      array = S{loopIndex};      % Access the contents of each cell
      % Do stuff with array
    end
    
16
gnovice

Getfieldアプローチは大丈夫です(ただし、現在MATLABを利用できないため、上記が機能しない理由は明確ではありません)。

代替データ構造については、MATLABセル配列を調べることもできます。また、さまざまな長さのベクトルを格納およびインデックス付けすることもできます。

5
Adam Holmberg

コロン表記を使用して、インデックスを回避できます。

S = struct('A', [1 2], 'B',[3 4 5]); 
SNames = fieldnames(S); 
for SName = [SNames{:}]
    stuff = S.(SName)
end
3
Niver

あなたが私が非常にうまくいったとわかった構造を使用する必要がある場合、最初にセルに変換することでしたが、あなたは両方の長所を持っています。

S = struct('A', [1 2], 'B',[3 4 5]); 
S_Cell = struct2cell(S);
%Then as per gnovice
for loopIndex = 1:numel(S_Sell)   % Loop over the number of cells
    array = S{loopIndex};         % Access the contents of each cell
    %# Do stuff with array
end

構造体で生成されたものに似たものを使用した後、マトリックスのようにアクセスする必要がありました。その場合は、

M = cell2mat(struct2cell(S));

マトリックスに変換するには

2
dabhand

ミックスに別の答えを追加するだけです。 @Niverのソリューションは気に入っていますが、1文字の名前のフィールドでのみ機能します。私が使用したソリューションは次のとおりです。

_S = struct('A', [1 2], 'B',[3 4 5], 'Cee', [6 7]); 
for SName = fieldnames(S)'
    stuff = S.(SName{1})
end
_

forはセル配列の列を反復処理します(そのためfieldnames(S)'の転置が行われます。各ループでSNameは1x1セル配列になるため、コンテンツインデックスを使用して最初の唯一の要素にアクセスします_SName{1}_。

0
sclarke81