如何动态访问结构体字段?

35

我有一个结构体,其中许多字段是不同长度的向量。我想在循环中按顺序访问这些字段。我尝试使用以下方法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个回答

46

尝试使用动态字段引用,即在括号中放置一个字符串,就像定义stuff行所示。

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

我同意Steve和Adam的观点。使用单元格。尽管对于其他情况的人来说,此语法是正确的!


16

这里我想要表达三点:

  • The reason you are getting an error in your above code is because of how you are indexing SNames. The function fieldnames returns a cell array of strings, so you have to use content indexing (i.e. curly braces) to access the string values. If you change the fourth line in your code to this:

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

    then your code should work without error.

  • As suggested by MatlabDoug, you can use dynamic field names to avoid having to use getfield (which yields cleaner looking code, in my opinion).

  • The suggestion from Adam to use a cell array instead of a structure is right on the mark. This is generally the best way to collect a series of arrays of different length into a single variable. Your code would end up looking something like this:

    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
    

使用单元数组而不是结构体虽然更简洁。 - Wok

5

getField方法是可以的(虽然我现在没有MATLAB可用,也不清楚为什么上面的方法行不通)。

如果你想要一种替代的数据结构,你也可以考虑MATLAB cell数组。它们也可以让你存储和索引长度不同的向量。


1
根据您对为什么使用结构体的描述,我同意Adam的观点。您应该考虑使用单元数组。 - Steve Eddins

2
您可以使用冒号表示法来避免使用索引:
S = struct('A', [1 2], 'B',[3 4 5]); 
SNames = fieldnames(S); 
for SName = [SNames{:}]
    stuff = S.(SName)
end

1
注意:这仅适用于字段名称只有一个字母的情况。这并不是通用的。 - Cris Luengo

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

将其转换为矩阵。

M = table2array(struct2table(S)); - BigChief

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}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接