Vra

Ek wil om te kombineer twee strukture met verskillende velde name.

Byvoorbeeld, wat begin met:

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

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

Ek sou graag:

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

Is daar'n meer doeltreffende manier as die gebruik van "fieldnames" en'n lus?

EDIT: Kom ons aanvaar dat in die geval van die veld naam konflikte ons voorkeur gee aan die A.

Was dit nuttig?

Oplossing

Sonder botsings, kan jy dit doen

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

En dit is redelik doeltreffend te maak. Maar struct foute op dubbele veldname en pre-kontrolering vir hulle met behulp van unique doodslaan prestasie tot op die punt dat 'n lus is beter. Maar hier is hoe dit sou lyk:

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

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

C=struct(M{:});

Jy kan in staat wees om 'n baster oplossing maak deur te aanvaar geen konflikte en die gebruik van 'n drie / vangs rondom die oproep om struct om grasieus te verneder om die konflik te hanteer geval.

Ander wenke

Kort antwoord: setstructfields (as jy die Sein Verwerking Toolbox).


Die amptelike oplossing is gepos deur Loren Shure op haar MathWorks blog, en gedemonstreer deur SCFrench hier en in Eitan T se antwoord op'n ander vraag.Egter, as jy het die Sein Verwerking Toolbox, 'n eenvoudige ongedokumenteerde funksie doen dit reeds - 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 dit gebruik fieldnames en'n for lus, so dit is'n gerief funksie met die fout kontrole en rekursie vir die velde wat hulself structs.

Voorbeeld

Die "oorspronklike" struct:

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

s = 
    color: 'orange'
    count: 2

'n tweede struct met'n nuwe waarde vir 'count', en'n nuwe veld, 'shape':

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

s2 = 
    count: 4
    shape: 'round'

Roeping setstructfields:

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

Die veld 'count' is opgedateer.Die veld 'shape' is bygevoeg.Die veld 'color' bly onveranderd.

NOTA:Sedert die funksie is ongedokumenteerde, dit kan verander of verwyder word op enige tyd.

Ek het 'n lekker oplossing op Exchange File gevind:. Catstruct

Sonder die toets van die prestasie wat ek kan sê dat dit presies wat ek wou. Dit kan hanteer dubbele velde natuurlik.

Hier is hoe dit werk:

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

s = catstruct(a,b)

gee

s = 

    f1: 1
    f2: 3
    f3: 4

Ek dink nie jy kan hanteer konflikte goed w/o'n lus, of doen ek dink jy sal nodig het om te verhoed dat een.(alhoewel ek veronderstel doeltreffendheid kan'n kwessie w/ baie baie velde...)

Ek gebruik'n funksie wat ek geskryf het'n paar jaar terug geroep setdefaults.m, wat kombineer een struktuur met die waardes van'n ander struktuur, waar een voorrang bo die ander in die geval van konflik.

% 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

Nou dat ek daaraan dink, ek is redelik seker dat die "ignoreer" insette is onnodig (jy kan net skakel die einde van die insette) maar ek is nie 100% seker van dat...so hier is'n eenvoudiger herskryf (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

en'n paar voorbeelde om dit te toets:

>> 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, kan 'n struct ander struct as een van sy lede het. Terwyl dit is nie presies dieselfde as wat jy vra, kan jy eindig óf met 'n situasie waar 'n mens struct bevat 'n ander, of een struct bevat twee structs, wat albei in besit wees dele van die inligting wat jy wil.

psuedocode: Ek kan nie onthou die werklike sintaksis

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

om toegang:     A.field3.field4;

of iets van die soort.

Of jy kan hê struct C hou beide 'n A en 'n B:

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

met toegang dan iets soos

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

Hoop dit help!

EDIT:. Beide van hierdie oplossings te vermy noem botsings

Ook, ek het nie gesien jou matlab tag. Deur konvensie, moet jy wil die vraag wysig om daardie stuk inligting in te sluit.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top