Каковы эффективные способы объединения двух структур в MATLAB?

Я хочу объединить две структуры с разными именами полей.

Например, начиная с:

A.field1 = 1;
A.field2 = 'a';

B.field3 = 2;
B.field4 = 'b';

Я бы хотел:

C.field1 = 1;
C.field2 = 'a';
C.field3 = 2;
C.field4 = 'b';

Есть ли более эффективный способ, чем использование "fieldnames" и цикла for?

РЕДАКТИРОВАТЬ: Предположим, что в случае конфликтов имен полей мы отдаем предпочтениеA.

Ответы на вопрос(5)

Решение Вопроса

Без столкновений можно обойтись

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
C=struct(M{:});

И это достаточно эффективно. Тем не мение,struct ошибки в дублирующих именах полей и предварительная проверка их с использованиемunique убивает производительность до такой степени, что цикл становится лучше. Но вот как это будет выглядеть:

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];

[tmp, rows] = unique(M(1,:), 'last');
M=M(:, rows);

C=struct(M{:});

Вы могли бы сделать гибридное решение, не допуская конфликтов и используя попытку / ловушку для вызоваstruct изящно унизить до случая урегулирования конфликта.

 magu_27 апр. 2015 г., 19:41
Первое решение может быть преобразовано в один вкладышcell2struct, Я не знаю о производительности этого все же.

Я нашел хорошийрешение по обмену файлами: catstruct.

Без тестирования производительности могу сказать, что он сделал именно то, что хотел. Это может иметь дело с дубликатами полей, конечно.

Вот как это работает:

a.f1 = 1;
a.f2 = 2;
b.f2 = 3;
b.f4 = 4;

s = catstruct(a,b)

Дам

s = 

    f1: 1
    f2: 3
    f3: 4

Короткий ответ:setstructfields (если у вас есть набор инструментов для обработки сигналов).

Официальное решение опубликовано Лорен Шуре наее блог MathWorksи продемонстрированоSCFrench здесь И вОтвет Эйтана Т на другой вопрос, Однако, если у вас есть набор инструментов для обработки сигналов, простая недокументированная функция уже делает это -setstructfields.

help setstructfields

 setstructfields Set fields of a structure using another structure
    setstructfields(STRUCTIN, NEWFIELDS) Set fields of STRUCTIN using
    another structure NEWFIELDS fields.  If fields exist in STRUCTIN
    but not in NEWFIELDS, they will not be changed.

Внутренне он используетfieldnames иfor цикл, так что это удобная функция с проверкой ошибок и рекурсией для полей, которые сами являются структурами.

пример

«Оригинальная» структура:

% struct with fields 'color' and 'count'
s = struct('color','orange','count',2)

s = 
    color: 'orange'
    count: 2

Вторая структура, содержащая новое значение для'count'и новое поле,'shape':

% struct with fields 'count' and 'shape'
s2 = struct('count',4,'shape','round')

s2 = 
    count: 4
    shape: 'round'

призваниеsetstructfields:

>> s = setstructfields(s,s2)
s = 
    color: 'orange'
    count: 4
    shape: 'round'

Поле'count' являетсяобновленный, Поле'shape' являетсядобавленной, Поле'color' остается неизменной.

НОТА: Поскольку функция недокументирована, она может быть изменена или удалена в любое время.

В C структура может иметь другую структуру в качестве одного из своих членов. Хотя это не совсем то, что вы просите, вы можете столкнуться с ситуацией, когда одна структура содержит другую, или одна структура содержит две структуры, каждая из которых содержит части информации, которую вы хотели.

psuedocode: я не помню фактический синтаксис.

A.field1 = 1;
A.field2 = 'a';
A.field3 = struct B;

для доступа: A.field3.field4;

или что-то в этом роде.

Или вы можете иметь структуру C, содержащую как A, так и B:

C.A = struct A;
C.B = struct B;

с доступом то что то типа

C.A.field1;
C.A.field2;
C.B.field3;
C.B.field4;

надеюсь это поможет!

РЕДАКТИРОВАТЬ: оба эти решения позволяют избежать коллизии имен.

Кроме того, я не видел вашmatlab тег. По договоренности вы должны отредактировать вопрос, включив в него эту информацию.

Я не думаю, что вы можете справиться с конфликтами без петель, и я не думаю, что вам нужно их избегать. (хотя я полагаю, что эффективность может быть проблемой со многими областями ...)

Я использую функцию, которую я написал несколько лет назад под названиемsetdefaults.m, который объединяет одну структуру со значениями другой структуры, где одна имеет приоритет над другой в случае конфликта.

% SETDEFAULTS sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 
%    SOUT = SETDEFAULTS(S, SDEF, OVERRIDE) does
%    the same function as above, but if OVERRIDE is 1,
%    it copies all fields of SDEF to SOUT.

function sout = setdefaults(s,sdef,override)
if (not(exist('override','var')))
    override = 0;
end

sout = s;
for f = fieldnames(sdef)'
    cf = char(f);
    if (override | not(isfield(sout,cf)))
        sout = setfield(sout,cf,getfield(sdef,cf));
    end
end

Теперь, когда я думаю об этом, я почти уверен, что ввод «переопределить» не нужен (вы можете просто изменить порядок входов), хотя я не уверен на 100% в этом ... так что вот более простое переписывание (setdefaults2.m):

% SETDEFAULTS2 sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 

function sout = setdefaults2(s,sdef)
sout = sdef;
for f = fieldnames(s)'
    sout = setfield(sout,f{1},getfield(s,f{1}));
end

и некоторые образцы, чтобы проверить это:

>> S1 = struct('a',1,'b',2,'c',3);
>> S2 = struct('b',4,'c',5,'d',6);
>> setdefaults2(S1,S2)

ans = 

    b: 2
    c: 3
    d: 6
    a: 1

>> setdefaults2(S2,S1)

ans = 

    a: 1
    b: 4
    c: 5
    d: 6
 Roman Shapovalov01 мар. 2013 г., 16:51
Начиная с MATLAB 6.5 (выпуск 13), динамические ссылки на поля могут использоваться для упрощения оператора внутри цикла:sout.(f{1}) = s.(f{1});
 Roman Shapovalov01 мар. 2013 г., 16:43
Спасибо, это именно то поведение, которое мне нужно. Интересно, почему это не является частью стандартной библиотеки.

Ваш ответ на вопрос