Was sind einige effiziente Möglichkeiten, um zu kombinieren zwei Strukturen in MATLAB?
Frage
Ich möchte Sie kombinieren zwei Strukturen mit unterschiedlichen Feldern-Namen.
Zum Beispiel, beginnend mit:
A.field1 = 1;
A.field2 = 'a';
B.field3 = 2;
B.field4 = 'b';
Ich möchte:
C.field1 = 1;
C.field2 = 'a';
C.field3 = 2;
C.field4 = 'b';
Gibt es einen effizienteren Weg, als mit "Feldnamen" und eine for-Schleife?
EDIT: Lassen Sie uns davon ausgehen, dass im Falle von Feld name Konflikte, die wir den Vorzug geben A
.
Lösung
Ohne Kollisionen, die Sie tun können
M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
C=struct(M{:});
Und das ist ziemlich effizient.Jedoch, struct
Fehler auf doppelte Feldnamen, und pre-prüfen Sie mit unique
tötet die Leistung bis zu dem Punkt, dass eine Schleife ist besser.Aber hier ist, was es Aussehen würde:
M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
[tmp, rows] = unique(M(1,:), 'last');
M=M(:, rows);
C=struct(M{:});
Sie könnten in der Lage sein, um eine hybrid-Lösung durch die Annahme, keine Konflikte und die Verwendung eines try/catch um den Anruf zu struct
ordnungsgemäß abbauen der Konfliktbearbeitung Fall.
Andere Tipps
Kurze Antwort: setstructfields
(wenn Sie die Signalverarbeitung Toolbox).
Die offizielle Lösung ist geschrieben von Loren Shure auf Ihr MathWorks blog, und demonstriert SCFrench hier und in Eitan T die Antwort auf eine andere Frage.Wenn Sie jedoch mit der Signal Processing Toolbox, eine einfache undokumentierte Funktion tut dies bereits - 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.
Intern verwendet es fieldnames
und eine for
Schleife, so ist es eine Komfort-Funktion mit der Fehlerüberprüfung und Rekursion für Felder, die sich structs.
Beispiel
Das "original" struct:
% struct with fields 'color' and 'count'
s = struct('color','orange','count',2)
s =
color: 'orange'
count: 2
Eine zweite Struktur mit einem neuen Wert für 'count'
, und ein neues Feld, 'shape'
:
% struct with fields 'count' and 'shape'
s2 = struct('count',4,'shape','round')
s2 =
count: 4
shape: 'round'
Aufrufen setstructfields
:
>> s = setstructfields(s,s2)
s =
color: 'orange'
count: 4
shape: 'round'
Bereich 'count'
ist aktualisiert.Bereich 'shape'
ist Hinzugefügt.Bereich 'color'
bleibt unverändert.
HINWEIS:Da die Funktion ist nicht dokumentiert, es kann sich ändern oder jederzeit entfernt werden.
Ich fand eine schöne Lösung auf Datei-Austausch:catstruct.
Ohne die Prüfung der Leistung kann ich sagen, dass es genau das Tat, was ich wollte.Es können deal mit doppelten Feldern natürlich.
Hier ist, wie es funktioniert:
a.f1 = 1;
a.f2 = 2;
b.f2 = 3;
b.f4 = 4;
s = catstruct(a,b)
Geben
s =
f1: 1
f2: 3
f3: 4
Ich glaube nicht, dass Sie behandeln können, Konflikte w/o eine Schleife, ich glaube auch nicht, dass Sie müssten, um zu vermeiden, eine.(obwohl ich vermute, Effizienz könnte ein Problem sein, w/ viele, viele Felder,...)
Ich benutze eine Funktion, die ich schrieb vor ein paar Jahren genannt setdefaults.m
, kombiniert eine Struktur mit den Werten eines anderen Aufbau, bei dem ein Vorrang vor den anderen im Fall eines Konflikts.
% 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
Jetzt, da ich darüber nachdenke, bin ich ziemlich sicher, dass die "override" - Eingabe ist nicht notwendig (Sie können schalten Sie einfach die Reihenfolge der Eingänge), aber ich bin mir nicht 100% sicher, dass...also hier ist ein einfacher umschreiben (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
und einige Proben zu testen:
>> 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
In C, eine Struktur, die kann haben eine andere Struktur als einem der Mitglieder.Während dies ist nicht genau das gleiche wie, was Sie fordern, könnten Sie am Ende entweder mit einer situation, in der eine struct mit einem anderen, oder eine Struktur enthält zwei Strukturen, beide Teile von der info, dass Sie wollte.
psuedocode:ich erinnere mich nicht an die eigentliche syntax.
A.field1 = 1;
A.field2 = 'a';
A.field3 = struct B;
für den Zugriff auf:A. field3.field4;
oder so etwas in der Art.
Oder Sie könnte haben struct C halten beide eine a-und Eine B:
C.A = struct A;
C.B = struct B;
mit Zugang ist dann so etwas wie
C.A.field1;
C.A.field2;
C.B.field3;
C.B.field4;
hoffe, das hilft!
EDIT:beide Lösungen vermeiden Sie Namenskonflikte.
Auch habe ich nicht sehen, Ihr matlab
tag.Gemäß der Konvention sollten Sie möchten, Bearbeiten Sie die Frage einschließen, die Stück-info.