Каковы эффективные способы объединения двух структур в 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.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
24
0
18 457
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

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

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. По соглашению вы должны захотеть отредактировать вопрос, включив в него эту информацию.

Ответ принят как подходящий

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

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{:});

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

Первое решение могло быть преобразовано в однострочник с помощью cell2struct. Хотя я не знаю, как это работает.

magu_ 27.04.2015 20:41

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

Я использую функцию 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

Теперь, когда я думаю об этом, я почти уверен, что ввод "override" не нужен (вы можете просто изменить порядок ввода), хотя я не уверен в этом на 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 Shapovalov 01.03.2013 19:43

Начиная с MATLAB 6.5 (Release 13), динамические ссылки на поля могут использоваться для упрощения оператора внутри цикла: sout.(f{1}) = s.(f{1});

Roman Shapovalov 01.03.2013 19:51

Я нашел хороший решение для обмена файлами: 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 (если у вас есть Signal Processing Toolbox).


Официальное решение опубликовано Лореном Шуре на ее блог 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'остается неизменной.

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

Другие вопросы по теме