如何动态访问结构字段?

时间:2009-12-10 16:06:27

标签: matlab matlab-struct

我有一个具有许多字段的结构,这些字段是不同长度的向量。我想按顺序访问循环中的字段。我试过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

我首先使用的是结构,因为数组会遇到不同字段长度的问题。有更好的替代方案吗?

6 个答案:

答案 0 :(得分:43)

尝试动态字段引用,将字符串放在括号中,如定义 stuff 的行所示。

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

我同意史蒂夫和亚当的观点。使用细胞。这种语法适用于其他情况下的人!

答案 1 :(得分:16)

我想在这里提出三点:

  • 您在上述代码中收到错误的原因是由于您对SNames编制索引的方式。函数fieldnames返回cell array个字符串,因此您必须使用content indexing(即大括号)来访问字符串值。如果您将代码中的第四行更改为:

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

    那么你的代码应该没有错误。

  • 根据MatlabDoug的建议,您可以使用dynamic field names来避免使用getfield(在我看来,这会产生更清晰的代码)。

    < / LI>
  • 使用suggestion from Adam代替结构的cell array正好在标记上。这通常是将一系列不同长度的数组收集到单个变量中的最佳方法。您的代码最终会看起来像这样:

    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
    

答案 2 :(得分:5)

getfield方法没问题(虽然我现在没有MATLAB可用,但我不清楚为什么上述方法不起作用。)

对于替代数据结构,您可能还需要查看MATLAB单元阵列。它们还允许您存储和索引不同长度的矢量。

答案 3 :(得分:3)

您可以使用冒号表示法来避免索引:

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

答案 4 :(得分:2)

如果你需要使用我发现效果非常好的结构,那么首先要转换为一个单元格,那么你就拥有了两全其美的结构。

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));

将其转换为矩阵

答案 5 :(得分:0)

只是为混音添加另一个答案。我喜欢@Niver的解决方案,但它只适用于单字母名称的字段。我使用的解决方案是:

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}