объединение 2 структур MATLAB - PullRequest
2 голосов
/ 15 марта 2019

У меня есть две небольшие структуры, которые я хотел бы объединить, но я не могу найти правильное решение. Структуры A и B имеют один общий столбец (одинаковые строковые значения), хотя важно, чтобы общие значения не обязательно были в одном и том же порядке между ними. Для примера я поставил их в другом порядке. Я хотел бы добиться того, что в структуре C ниже, где информация из обеих структур организована вместе:

A(1).condition = 'con1';
A(1).y = rand(10, 1);
A(2).condition = 'con2';
A(2).y = rand(10, 1);

B(1).condition = 'con2';
B(1).z = normrnd(0,1);
B(2).condition = 'con1';
B(2).z = normrnd(0,1);

% Desired output:
C = A;
C(1).z = B(2).z;
C(2).z = B(1).z

Ответы [ 3 ]

2 голосов
/ 16 марта 2019

Вам необходимо:

  1. Найдите порядок, в котором элементы одного массива структуры соответствуют другому, на основе значения condition.
  2. Скопировать каждое поле в B(i) в соответствующий элемент массива A. Я предполагаю, что в B больше полей, чем просто z и condition.

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

[~,I] = ismember({A.condition},{B.condition});

Обратите внимание, что {A.condition} - это массив ячеек со всеми строками condition. B(I) - это массив структур B, упорядоченный для соответствия A.

Шаг 2 можно выполнить, как в ответе rahnema1 , который мы обобщаем здесь для копирования нескольких полей, используя цикл над именами полей и используя имена динамических полей :

fields = fieldnames(B);
fields = setdiff(fields,'condition'); % don't copy over this field
for ii = 1:numel(fields)
   [A.(fields{ii})] = B(I).(fields{ii});
end

Тестирование:

A(1).condition = 'con1';
A(1).y = [1,1,1];
A(2).condition = 'con2';
A(2).y = [2,2];
A(3).condition = 'con3';
A(3).y = [3,3,3];

B(1).condition = 'con2';
B(1).z = 2;
B(1).x = 'b';
B(2).condition = 'con3';
B(2).z = 3;
B(2).x = 'c';
B(3).condition = 'con1';
B(3).z = 1;
B(3).x = 'a';

[~,I] = ismember({A.condition},{B.condition});

fields = fieldnames(B);
fields = setdiff(fields,'condition'); % don't copy over this field
for ii = 1:numel(fields)
   [A.(fields{ii})] = B(I).(fields{ii});
end

Это дает следующую структуру A:

>> A(1)

ans = 

  struct with fields:

    condition: 'con1'
            y: [1 1 1]
            x: 'a'
            z: 1

>> A(2)

ans = 

  struct with fields:

    condition: 'con2'
            y: [2 2]
            x: 'b'
            z: 2

>> A(3)

ans = 

  struct with fields:

    condition: 'con3'
            y: [3 3 3]
            x: 'c'
            z: 3
1 голос
/ 16 марта 2019

Вы можете назначить comma separated list другому списку через запятую:

C = A;
[C(2:-1:1).z] = B.z;

или

[C.z] = B(2:-1:1).z;
0 голосов
/ 16 марта 2019

Это не элегантно, но должно работать:

C = A
for idx_A = 1:length(A)
    for idx_B = 1:length(B)
        if strcmp(A(idx_A).condition, B(idx_B).condition)
            C(idx_A).z = B(idx_B).z
        end
    end
end

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

A.condition = {'con1', 'con2'};
A.y = [rand(10, 1), rand(10, 1)]

Это облегчает многие операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...