Итерация через имена полей структуры в MATLAB

54

Мой вопрос легко суммируется как: "Почему следующие не работают?"

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'.

Я не могу обойти его.

Теги:
matlab-struct

4 ответа

71
Лучший ответ

Вам нужно использовать фигурные скобки ({}) для доступа к 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
  • 2
    Ваш ответ невероятно полезен и прояснил некоторые вещи, которые беспокоили меня буквально в течение многих лет.
13

Так как 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
4

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

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

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

name_as_char = 'a'
name_as_cellstr = {'a'}
0

Вы можете использовать для каждого инструментария 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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню