2008-09-02 9 views
21

異なるフィールド名を持つ2つの構造を結合したいと考えています。例えばMATLABで2つの構造を結合する効率的な方法は何ですか?

は、で始まる:

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

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

は私が持っていると思い

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

"フィールド名" とforループを使用するよりも効率的な方法はありますか?

編集:フィールド名の競合の場合は、Aを優先するとします。

答えて

15

衝突がなければ、あなたは

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に呼び出しの周りのtry/catchを使用してハイブリッドソリューションを作ることができるかもしれません。

+0

第1の溶液は、「cell2struct」によって1つのライナーに変換することができた。私はそれのパフォーマンスについてはわかりません。 –

2

Cでは、structはそのメンバーの1つとして別の構造体を持つことができます。これはあなたが求めているものとまったく同じではありませんが、どちらか一方の構造体に別の構造体が含まれているか、または一方の構造体に2つの構造体が含まれていて、どちらも必要な情報の部分を保持している状況で終わる可能性があります。

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; 

のような希望を!

EDIT:これらのソリューションは両方とも、名前の衝突を回避します。

また、matlabタグが表示されませんでした。慣例により、その情報を含めるように質問を編集する必要があります。

4

私はあなたがループなしで競合をうまく処理することはできないと思います。 (効率は多くの分野で問題になると思われますが...)

私は数年前に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 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 

し、それをテストするためのいくつかのサンプル::ので、ここでは単純に書き換え(setdefaults2.m)です

>> 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 
+0

ありがとう、これは私が必要とする動作です。なぜ標準ライブラリの一部ではないのだろうか。 –

+0

MATLAB 6.5(Release 13)では、動的フィールド参照を使用して、ループ内のステートメントを簡略化することができます: 'sout。(f {1})= s。(f {1});' –

5

私は素敵なsolution on File Exchange: catstructを発見しました。

パフォーマンスをテストせずに、私が望んだのとまったく同じだと言うことができます。 もちろん、重複フィールドを扱うことができます。ここで

は、それがどのように働くかである:(あなたはSignal Processing Toolboxのを持っている場合)setstructfields

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

s = catstruct(a,b) 

s = 

    f1: 1 
    f2: 3 
    f3: 4 
8

に短い答えを与えるだろう。


公式ソリューションはher MathWorks blogにローレンのShureによって投稿され、そしてSCFrench hereによって及びEitan T's answer to a different questionで明らかにしました。ただし、Signal Processing Toolboxを使用している場合は、文書化されていない簡単な関数が既にこれを行います。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. 

内部的にはfieldnamesforループを使用していますので、構造体自身のフィールドのためのエラーチェックと再帰と便利な関数です。

"オリジナル" 構造体:

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

s = 
    color: 'orange' 
    count: 2 

'count'の新しい値を含む第二の構造体、及び新たなフィールド、'shape'setstructfieldsを呼び出す

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

s2 = 
    count: 4 
    shape: 'round' 

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

フィールド'count'は、に更新されています。フィールド'shape'は、には、が追加されています。フィールド'color'は変更されずにのままです。

:この機能は文書化されていないため、いつでも変更または削除される可能性があります。

関連する問題