J'ai une structure avec beaucoup de champs qui sont des vecteurs de différentes longueurs. Je voudrais accéder aux champs dans une boucle, dans l'ordre. J'ai essayé getfield comme suit, mais MATLAB n'aime pas cela. Comment puis-je faire ceci?
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
J'utilise des structures en premier lieu car un tableau aurait des problèmes avec les différentes longueurs de champs. Y a-t-il une meilleure alternative à cela?
Essayez la référence de champ dynamique où vous mettez une chaîne entre parenthèses, comme indiqué sur la ligne définissant stuff .
S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for loopIndex = 1:numel(SNames)
stuff = S.(SNames{loopIndex})
end
Je suis d'accord avec Steve et Adam. Utilisez des cellules. Cette syntaxe convient toutefois aux personnes se trouvant dans d'autres situations!
Je voudrais faire trois remarques ici:
La raison pour laquelle vous obtenez une erreur dans le code ci-dessus est due à la façon dont vous indexez SNames
. La fonction fieldnames
renvoie un tableau de cellules de chaînes, vous devez donc utiliser indexation du contenu (par exemple, des accolades) pour accéder aux valeurs des chaînes. Si vous modifiez la quatrième ligne de votre code en ceci:
field = getfield(S, SNames{loopIndex});
alors votre code devrait fonctionner sans erreur.
Comme suggéré par MatlabDoug , vous pouvez utiliser les noms de champs dynamiques pour éviter de devoir utiliser getfield
(qui produit un code plus propre, à mon avis).
La suggestion d'Adam d'utiliser un tableau de cellules au lieu d'une structure est exacte sur la marque. C'est généralement le meilleur moyen de rassembler une série de tableaux de différentes longueurs en une seule variable. Votre code finirait par ressembler à ceci:
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
L’approche de getfield est acceptable (bien que MATLAB ne soit pas disponible pour le moment et j’ignore pourquoi ce qui précède ne fonctionne pas).
Pour une autre structure de données, vous pouvez également consulter les tableaux de cellules MATLAB. Ils vous permettraient également de stocker et d’indexer des vecteurs de différentes longueurs.
Vous pouvez utiliser la notation deux points pour éviter les index:
S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for SName = [SNames{:}]
stuff = S.(SName)
end
Si vous avez besoin d'utiliser une structure, ce que j'ai trouvé très bien fonctionné était de convertir d'abord en cellule, vous avez le meilleur des deux mondes.
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
J'ai utilisé quelque chose de similaire pour quelque chose qui a été généré dans une structure et puis j'ai eu besoin d'y accéder comme une matrice, dans ce cas c'était aussi simple que
M = cell2mat(struct2cell(S));
Pour le convertir en matrice
Juste pour ajouter une autre réponse au mélange. J'aime la solution de @Niver, mais cela ne fonctionne que pour les champs avec des noms à une seule lettre. La solution que j'ai utilisée était:
S = struct('A', [1 2], 'B',[3 4 5], 'Cee', [6 7]);
for SName = fieldnames(S)'
stuff = S.(SName{1})
end
for
va parcourir les colonnes d'un tableau de cellules (d'où la transposition sur fieldnames(S)'
. Pour chaque boucle, SName devient un tableau de cellules 1x1. Nous utilisons l'indexation de contenu pour accéder au premier et unique élément avec SName{1}
.