Можно ли получить доступ к значениям этой структуры / изменить их без использования цикла for?

Вот мой начальный массив структуры:

A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';

Я хочу изменить значения поля C на основе значений Values и индексы IndexingArray:

Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

Итак, мой новый массив структуры будет:

A(1).B.C = 'b';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'b';

Есть ли способ сделать это без использования цикла for?

2 ответа

Вы можете сделать это без использования циклов deal и синтаксис списка через запятую, но читать его может быть немного сложнее:

% Initialize A:
A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

temp = [A.B];           % Structure array containing B substructures
[temp.C] = deal(Values{IndexingArray+1});  % Set field C of each structure element
temp = num2cell(temp);  % Convert to a cell array of 1-by-1 structures
[A.B] = deal(temp{:});  % Update B substructures

А в более новых версиях MATLAB вы можете опустить deal в целом:

temp = [A.B];
[temp.C] = Values{IndexingArray+1};
temp = num2cell(temp);
[A.B] = temp{:};

Это должно позволить вам обновить B а также C поля, не влияя на любые другие поля, которые могут существовать в вашей более сложной структуре.

Вместо изменения значения проще перестроить массив структур.

  • Получить значение по IndexingArray:

    val = Values(IndexingArray+1);
    
  • Построить массив структур, используя cell2structи преобразовать в массив ячеек, используя num2cell:

    T = num2cell(cell2struct(val, {'C'}, 1));
    
  • Перерабатывать T результат для массива структур, использующих cell2struct:

    A = cell2struct(T', {'B'}, 1);
    

Вот пример кода для создания A:

Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

val = Values(IndexingArray+1);

T = num2cell(cell2struct(val, {'C'}, 1));

A = cell2struct(T', {'B'}, 1);

Построение А в одной строке кода:

A = cell2struct((num2cell(cell2struct(Values(IndexingArray+1), {'C'}, 1)))', {'B'}, 1);

Результат (для тестирования):

>> A(1).B.C

ans =

b

>> A(2).B.C

ans =

b

>> A(3).B.C

ans =

a

>> A(4).B.C

ans =

b

Решение с использованием arrayfun:

val = Values(IndexingArray+1);

A = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4)

Обновить конкретные элементы A:

В случае, если вам нужно обновить определенные элементы, вместо того, чтобы перезаписать AВы можете подать заявку arrayfun выборочно, к индексам, вы знаете, что нужно обновить.

Пример:

Предполагать A длина составляет 6 элементов, и вам нужно обновить первые 4, вы можете использовать следующий код:

A(1:4) = arrayfun(@(x) struct('B', struct('C', val{x})), 1:4);

Предположим, вы знаете, что вам нужно только обновить A(1) а также A(4)Вы можете использовать следующий пример:

A(1).B.C = 'a';
A(2).B.C = 'b';
A(3).B.C = 'a';
A(4).B.C = 'a';
A(5).B.C = 'c';
A(6).B.C = 'd';

Values = {'a', 'b'};
IndexingArray = [1 1 0 1];

val = Values(IndexingArray+1);

%List of indices of A to update
indices = [1, 4];

A(indices) = arrayfun(@(x) struct('B', struct('C', val{x})), indices);
Другие вопросы по тегам