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.

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top