Как эффективно взять линейную комбинацию из двух различных структурных массивов?


Предположим, что у меня есть два структурных массива с соответствующими полями, а также содержимое обоих массивов в данном поле одинакового размера:

A.field1 = [1,2,3]
A.field2 = 5

B.field1 = [4,5,6]
B.field2 = 9

Я хотел бы взять линейную комбинацию всех данных в каждом поле. В нашем примере это будет означать, что если x и y являются константами, я хотел бы получить структурный массив C такой, что

C.field1 = x*(A.field1) + y*(B.field1)
C.field2 = x*(A.field2) + y*(B.field2)

Моей первой догадкой было использовать команду structfun , но это, похоже, только один структурный массив в качестве входных данных, где мне понадобились бы и A, и B, чтобы быть входными данными.

Грубый способ-это извлечение всех данных и хранение их в отдельных переменных, взять линейную комбинацию и собрать их обратно в структурный массив. Но, похоже, должен быть более простой способ (или, по крайней мере, тот, который быстрее печатается, мои массивы не так малы).
3 5

3 ответа:

Далее предполагается, что у вас есть два структурных массива с произвольным числом совпадающих полей (n - одинаковое для обеих структур), которые не являются вложенными (нет A.field1.field2)

Ванильная петля:

x = 2;
y = 3;
names = fieldnames(A); % returns n x 1 cell array

for n = 1:length(names)
    C.(names{n}) = x*A.(names{n}) + y*B.(names{n});
end

Вывод:

C = 

    field1: [14 19 24]
    field2: 37

Альтернатива с использованием cellfun:

x = 2;
y = 3;
names = fieldnames(A);
A2 = struct2cell(A);
B2 = struct2cell(B);

C2 = cellfun(@(A,B) x*A+3*B, A2,B2,'UniformOutput',0);
C2 = cell2struct(C2,names)

Вывод:

C2 = 

    field1: [14 19 24]
    field2: 37

Код

%%// Input structs
A.field1 = [1,2,3]
A.field2 = 5
A.field3 = [8 9];

B.field1 = [4,5,6]
B.field2 = 9
B.field3 = [11 12];

%%// Scaling factors
scaling_factors = [2; 3]; %%// This is your [x y]
cellA = cellfun(@(x) x*scaling_factors(1),struct2cell(A),'un',0)
cellB = cellfun(@(x) x*scaling_factors(2),struct2cell(B),'un',0)
cellC = cellfun(@plus, cellA, cellB,'uni',0)

C = cell2struct(cellC, fieldnames(A))

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

result = cell2struct( cellfun(@(x,y){1/4*x+3/4*y}, struct2cell(A),struct2cell(B)), fieldnames(A));

Тот же код, но с лучшим стилем (я ненавижу однострочные):

 cellA = struct2cell(A);
 cellB = struct2cell(B);
 cellResult = cellfun(@(x,y){1/4*x+3/4*y},cellA,cellB);
 result = cell2struct(cellResult , fieldnames(A));