Как я могу динамически обращаться к полям структуры?
У меня есть структура со многими полями, которые являются векторами разной длины. Я хотел бы получить доступ к полям внутри цикла, по порядку. Я попробовал 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
Я использую структуры в первую очередь потому, что у массива возникнут проблемы с разными полями. Есть ли лучшая альтернатива этому?
Ответы
Ответ 1
Попробуйте ссылку на динамическое поле, где вы помещаете строку в круглую скобку, как показано на строке, определяющей материал.
S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for loopIndex = 1:numel(SNames)
stuff = S.(SNames{loopIndex})
end
Я согласен со Стивом и Адамом. Используйте ячейки. Этот синтаксис подходит для людей в других ситуациях, хотя!
Ответ 2
Есть три момента, которые я хотел бы сделать здесь:
-
Причина, по которой вы получаете ошибку в своем предыдущем коде, связана с тем, как вы индексируете SNames
. Функция fieldnames
возвращает массив ячеек строки, поэтому вам нужно использовать индексацию содержимого (то есть фигурные скобки) для доступа к строковым значениям. Если вы измените четвертую строку в своем коде на это:
field = getfield(S, SNames{loopIndex});
тогда ваш код должен работать без ошибок.
-
Как предложено MatlabDoug, вы можете использовать имена динамических полей, чтобы избежать использования getfield
(что, на мой взгляд, дает более чистый код).
-
Предложение от Adam вместо
Ответ 3
Подход Getfield подходит (хотя у меня нет MATLAB, доступного прямо сейчас, и мне не ясно, почему выше не работает).
Для альтернативной структуры данных вы также можете посмотреть в массивы ячеек MATLAB. Они также позволят вам хранить и индексировать векторы различной длины.
Ответ 4
Вы можете использовать двоеточие, чтобы избежать индексов:
S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for SName = [SNames{:}]
stuff = S.(SName)
end
Ответ 5
Если вам нужно использовать структуру, то, что я нашел, работало очень хорошо, чтобы сначала преобразовать в ячейку, тогда у вас есть лучшее из обоих миров.
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));
Чтобы преобразовать его в матрицу
Ответ 6
Просто добавьте еще один ответ на микс. Мне нравится решение от @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}
.