2008-09-02 12 views
21

मैं अलग-अलग फ़ील्ड नामों के साथ दो संरचनाओं को जोड़ना चाहता हूं।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" और एक पाश के लिए उपयोग करने की तुलना एक अधिक कुशल तरीका है?

संपादित करें: मान लीजिए कि फ़ील्ड नाम के संघर्ष के मामले में हम 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 करने के लिए कॉल के आसपास आज़माएं/कैच का उपयोग कर शान से संघर्ष मामले से निपटने के लिए नीचा दिखाने से एक संकर समाधान करने में सक्षम हो सकता है।

+0

पहला समाधान 'सेल 2 स्ट्रक्चर' द्वारा एक लाइनर में परिवर्तित किया जा सकता है। हालांकि मैं इसके प्रदर्शन के बारे में नहीं जानता। –

2

सी में, एक संरचना में इसके सदस्यों में से एक के रूप में एक और संरचना हो सकती है। हालांकि यह वही नहीं है जो आप पूछ रहे हैं, आप या तो ऐसी परिस्थिति के साथ समाप्त हो सकते हैं जहां एक संरचना में एक और होता है, या एक संरचना में दो structs होते हैं, जिनमें से दोनों जानकारी के कुछ हिस्से होते हैं जिन्हें आप चाहते थे।

psuedocode: मुझे वास्तविक वाक्यविन्यास याद नहीं है।

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

एक्सेस करने के लिए: एफील्ड 3.फील्ड 4;

या इस तरह का कुछ।

या आप struct सी दोनों एक एक और एक बी पकड़ हो सकता है:

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

तो पहुँच कुछ के साथ

तरह
C.A.field1; 
C.A.field2; 
C.B.field3; 
C.B.field4; 

आशा है कि यह मदद करता है!

संपादित करें: इन दोनों समाधान टकराव नामकरण से बचें।

इसके अलावा, मुझे आपके matlab टैग नहीं दिखाई दिए। सम्मेलन से, आपको उस जानकारी को शामिल करने के लिए प्रश्न को संपादित करना चाहिए।

4

मुझे नहीं लगता कि आप विवादों को अच्छी तरह से एक लूप को संभाल सकते हैं, और न ही मुझे लगता है कि आपको एक से बचने की आवश्यकता होगी। (हालांकि मुझे लगता है कि दक्षता एक मुद्दा हो सकता है w/कई फ़ील्ड ...)

मैं कुछ फ़ंक्शन का उपयोग करता हूं जिसे मैंने कुछ साल पहले 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 

और कुछ नमूनों में यह परीक्षण करने के लिए:

>> 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 (रिलीज 13) के रूप में, लूप के अंदर कथन को सरल बनाने के लिए गतिशील फ़ील्ड संदर्भों का उपयोग किया जा सकता है: 'south। (F {1}) = s। (F {1});' –

5

मैं एक अच्छा solution on File Exchange: catstruct पाया है इसलिए यहाँ एक सरल पुनर्लेखन (setdefaults2.m) है।

प्रदर्शन का परीक्षण किए बिना मैं कह सकता हूं कि यह वही था जो मैं चाहता था। यह पाठ्यक्रम के डुप्लिकेट फ़ील्ड से निपट सकता है।

यह ऐसे काम करता है:

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

s = catstruct(a,b) 

s = 

    f1: 1 
    f2: 3 
    f3: 4 
8

लघु जवाब देंगे: setstructfields (आप सिग्नल प्रोसेसिंग उपकरण बॉक्स है)।


आधिकारिक समाधान her MathWorks blog पर लोरेन शुरे द्वारा पोस्ट की गई, और SCFrench here द्वारा और Eitan T's answer to a different question में दर्शाया गया है। हालांकि, अगर आपके पास सिग्नल प्रोसेसिंग टूलबॉक्स है, तो यह एक सरल अनियंत्रित फ़ंक्शन पहले से ही करता है - 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 पाश का उपयोग करता है, तो यह क्षेत्रों कि खुद structs हैं के लिए त्रुटि जाँच और प्रत्यावर्तन के साथ एक सुविधा कार्य है।

उदाहरण

"मूल" struct:

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

s = 
    color: 'orange' 
    count: 2 

एक दूसरा struct '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'अपरिवर्तित बनी हुई है।

नोट: चूंकि फ़ंक्शन अनियंत्रित है, इसलिए यह किसी भी समय बदल सकता है या हटाया जा सकता है।