2010-05-10 5 views
58

Мой вопрос легко суммируется как: «Почему следующие не работают?»Итерация по именам объектов структуры в MATLAB

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

Я не могу опустить голову.

ответ

75

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

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

Использование скобок access data in your cell array просто возвращают другой массив ячеек, который отображается в отличие от массив символов:

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

Ваш ответ невероятно полезен и прояснил некоторые вещи, которые буквально меня били в течение многих лет. –

5

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

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

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

name_as_char = 'a' 
name_as_cellstr = {'a'} 
14

С 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 
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 

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