Durch Strukturfeldnamen in MATLAB iterieren

74

Meine Frage lässt sich leicht wie folgt zusammenfassen: "Warum funktioniert Folgendes nicht?"

teststruct = struct('a',3,'b',5,'c',9)

fields = fieldnames(teststruct)

for i=1:numel(fields)
  fields(i)
  teststruct.(fields(i))
end

Ausgabe:

ans = 'a'

??? Argument to dynamic structure reference must evaluate to a valid field name.

Zumal teststruct.('a') funktioniert da . Und fields(i)druckt aus ans = 'a'.

Ich kann es nicht verstehen.

noio
quelle

Antworten:

94

Sie müssen geschweifte Klammern ( {}) verwenden, um darauf zuzugreifen fields, da die fieldnamesFunktion ein Zellenarray von Zeichenfolgen zurückgibt :

for i = 1:numel(fields)
  teststruct.(fields{i})
end

Wenn Sie Klammern verwenden, um auf Daten in Ihrem Zellenarray zuzugreifen, wird nur ein anderes Zellenarray zurückgegeben, das anders als ein Zeichenarray angezeigt wird:

>> fields(1)  % Get the first cell of the cell array

ans = 

    'a'       % This is how the 1-element cell array is displayed

>> fields{1}  % Get the contents of the first cell of the cell array

ans =

a             % This is how the single character is displayed
gnovice
quelle
2
Ihre Antwort ist unglaublich hilfreich und hat einige Dinge geklärt, die mich seit Jahren buchstäblich nerven.
Mad Physicist
15

Da fieldsoder fnssind Zellenarrays, müssen Sie mit geschweiften Klammern indizieren, {}um auf den Inhalt der Zelle, dh die Zeichenfolge, zuzugreifen.

Beachten Sie, dass Sie anstelle einer Schleife auch eine Nummer fieldsdurchlaufen können, indem Sie eine übersichtliche Matlab-Funktion verwenden, mit der Sie jedes Array durchlaufen können. Die Iterationsvariable nimmt den Wert jeder Spalte des Arrays an.

teststruct = struct('a',3,'b',5,'c',9)

fields = fieldnames(teststruct)

for fn=fields'
  fn
  %# since fn is a 1-by-1 cell array, you still need to index into it, unfortunately
  teststruct.(fn{1})
end
Jonas
quelle
5

Ihr fns ist ein cellstr-Array. Sie müssen mit {} anstelle von () indizieren, um die einzelne Zeichenfolge als Zeichen auszugeben.

fns{i}
teststruct.(fns{i})

Wenn Sie mit () darauf indizieren, wird ein 1-langes cellstr-Array zurückgegeben, das nicht das gleiche Format wie das char-Array hat, das die dynamische Feldreferenz ". (Name)" benötigt. Die Formatierung, insbesondere in der Anzeigeausgabe, kann verwirrend sein. Versuchen Sie dies, um den Unterschied zu erkennen.

name_as_char = 'a'
name_as_cellstr = {'a'}
Andrew Janke
quelle
1

Sie können die für jede Toolbox unter http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each verwenden .

>> signal
signal = 
sin: {{1x1x25 cell}  {1x1x25 cell}}
cos: {{1x1x25 cell}  {1x1x25 cell}}

>> each(fieldnames(signal))
ans = 
CellIterator with properties:

NumberOfIterations: 2.0000e+000

Verwendung:

for bridge = each(fieldnames(signal))
   signal.(bridge) = rand(10);
end

Ich mag es sehr. Dank geht natürlich an Jeremy Hughes, der die Toolbox entwickelt hat.

Jan.
quelle