2010-05-10 20 views
58

Meine Frage ist leicht zusammengefasst als: "Warum funktioniert das folgende nicht?"Iterieren durch Struct Feldnamen in MATLAB

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

fields = fieldnames(teststruct) 

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

Ausgang:

ans = 'a' 

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

Vor allem, da teststruct.('a')tut Arbeit. Und fields(i) druckt ans = 'a' aus.

Ich kann mich nicht darum kümmern.

Antwort

75

Sie haben geschweiften Klammern zu verwenden ({}) fields zuzugreifen, da die fieldnames Funktion eine cell array von Strings zurückgibt:

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

Klammern access data in your cell array Verwendung wird nur eine andere Zelle Array zurück, die aus unterschiedlich angezeigt wird ein Zeichenarray:

>> 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 
+2

Ihre Antwort ist unglaublich hilfreich und hat einige Dinge aufgeklärt, die mich seit Jahren buchstäblich nerven. –

5

Ihr fns ist ein Zellenfeld. Sie müssen mit {} statt() indizieren, um den einzelnen String als char zu erhalten.

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

Indexing in ihn mit() gibt ein 1-long cellstr Array, das nicht das gleiche Format wie die char Array ist, dass der "(Name)" dynamische Feldreferenz will. Die Formatierung, insbesondere in der Display-Ausgabe, kann verwirrend sein. Um den Unterschied zu sehen, versuchen Sie es.

name_as_char = 'a' 
name_as_cellstr = {'a'} 
14

Da fields oder fns Zellen-Arrays sind, haben Sie mit geschweiften Klammern {}, um zu indizieren den Inhalt der Zelle zu gelangen, das heißt die Zeichenfolge.

Beachten Sie, dass Sie anstelle einer Schleife über eine Zahl auch direkt über fields eine Schleife ziehen können, indem Sie eine ordentliche Matlab-Funktion verwenden, mit der Sie jedes Array durchlaufen können. Die Iterationsvariable übernimmt den Wert jeder Spalte des Arrays.

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 
0

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

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

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

NumberOfIterations: 2.0000e+000 

Verbrauch:

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

ich es viel sehr ähnlich. Kredit geht natürlich an Jeremy Hughes, der die Toolbox entwickelt hat.