Ітерація через назви полів структури в MATLAB


74

Моє запитання легко узагальнити так: "Чому наступне не працює?"

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

Я не можу обійти головою.

Відповіді:


94

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

15

Оскільки масиви комірок 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

Ваш fns - це масив стільників. Вам потрібно проіндексувати його за допомогою {} замість (), щоб отримати один рядок як char.

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

Індексування до нього за допомогою () повертає 1-довгий масив стільників, який не є тим самим форматом, що і масив char, який хоче посилання на динамічне поле ". (Name)". Форматування, особливо на виході з дисплея, може заплутати. Щоб побачити різницю, спробуйте це.

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

1

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

Мені це дуже подобається. Звичайно, заслуга Джеремі Хьюза, який розробив набір інструментів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.