Итерация через имена полей структуры в MATLAB - PullRequest
67 голосов
/ 10 мая 2010

Мой вопрос легко резюмируется как: "Почему не работает следующее?" teststruct = struct('a',3,'b',5,'c',9) fields = fieldnames(teststruct) for i=1:numel(fields) fields(i) teststruct.(fields(i)) end Выход:

ans = 'a'

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

Тем более что teststruct.('a') работает . И fields(i) распечатывает ans = 'a'.

Я не могу обдумать это.

Ответы [ 4 ]

89 голосов
/ 10 мая 2010

Вы должны использовать фигурные скобки ({}) для доступа к fields, поскольку функция fieldnames возвращает массив ячеек строк:

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

Использование скобок для доступа к данным в вашем массиве ячеек просто вернет другой массив ячеек, который отображается иначе, чем массив символов:

>> 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
15 голосов
/ 10 мая 2010

Поскольку fields или fns являются массивами ячеек, вам необходимо индексировать фигурными скобками {}, чтобы получить доступ к содержимому ячейки, то есть строке.

Обратите внимание, что вместо зацикливания числа вы также можете зациклить fields напрямую, используя удобные функции Matlab, которые позволяют проходить через любой массив. Переменная итерации принимает значение каждого столбца массива.

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
5 голосов
/ 10 мая 2010

Ваш fns является массивом cellstr. Вам нужно проиндексировать его с помощью {} вместо (), чтобы вывести единственную строку как char.

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

Индексирование к нему с помощью () возвращает массив cellstr длиной 1, который отличается от формата массива, который требуется для ссылки динамического поля ". (Name)". Форматирование, особенно в выводе на экран, может привести к путанице. Чтобы увидеть разницу, попробуйте это.

name_as_char = 'a'
name_as_cellstr = {'a'}
0 голосов
/ 29 февраля 2016

Вы можете использовать для каждого набора инструментов от http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each.

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

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

NumberOfIterations: 2.0000e+000

Использование:

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

Мне это очень нравится. Конечно, стоит отдать должное Джереми Хьюзу, который разработал набор инструментов.

...