2011-10-11 24 views
7

मैं दो सूचियों, एक नकली और एक असली, जैसे:संपत्ति के आधार पर दो सूचियों को मर्ज कैसे करें?

पहले

// fake (list 1) 
{ ID = 1, Year = 2011, X = "" } 
, { ID = 2, Year = 2012, X = "" } 
, { ID = 3, Year = 2013, X = "" } 

// real (list 2) 
{ ID = 35, Year = 2011, X = "Information" } 
, { ID = 77, Year = 2013, X = "Important" } 

मैं विलय करने के लिए उन्हें वर्ष के लिए देख चाहते हैं, परिणाम होना चाहिए:

के बाद

{ ID = 35, Year = 2011, X = "Information" } 
, { ID = 2, Year = 2012, X = "" } 
, { ID = 77, Year = 2013, X = "Important" } 

इसे तत्वों को हटाना होगा उसी वर्ष के साथ पहली सूची में और आदेश को रखते हुए, पहली सूची में दूसरी सूची में समकक्ष वर्ष के साथ तत्व जोड़ें।

लिंकक का उपयोग करके मैं इसे कैसे कर सकता हूं?

+0

शायद आप पहले/बाद में चित्रण का उपयोग करके स्पष्टीकरण दे सकते हैं? अब आप पूरी तरह से – sehe

उत्तर

9

आपको लगता है कि का उपयोग कर एक "बाएं में शामिल होने के" करने के लिए सक्षम होना चाहिए:

from f in fake 
join r in real 
on f.Year equals r.Year 
into joinResult 
from r in joinResult.DefaultIfEmpty() 
select new 
     { 
      ID = r == null ? f.ID : r.ID, 
      Year = f.Year, 
      X = r == null ? f.X : r.X 
     }; 
+0

खो चुके हैं कि पिछली पंक्ति 'f.X' वापस आनी चाहिए जब यह स्थिति सही है, यह मानने के बजाय कि यह हमेशा खाली स्ट्रिंग होगी, लेकिन अन्यथा, +1 –

+0

@djacobson - पहले ही तय हो चुका है। –

+0

हमें उत्तर संपादन, एसओ, गंभीरता से AJAX- शैली रीफ्रेश दें। ;) –

5

जस्टिन क्वेरी यह करने के लिए सबसे कारगर तरीका है, लेकिन आप समान वस्तुओं रखने (और नहीं बनाने के साथ संबंध रहे हैं क्वेरी से नए रिकॉर्ड) आप इस तरह यह कर सकता है: इसके बजाय नकली सूची निर्धारित अपने आप को

var combined = from f in fake 
       let r = (from r1 in real 
         where r1.Year == f.Year 
         select r1).SingleOrDefault() 
       select r ?? f; 
1

, Linq यह तुम्हारे लिए क्या कर रही है कोशिश:

Enumerable.Range(2011,3) //2011, 2012, 2013    
      //use the overload that provides a 0-based ordinal position of each element 
      .Select(x,i=> new {ID = i+1, Year = x, X = String.Empty) 
      //now you have your fake list; join with the "real" list based on Year fields, 
      //taking the real element wherever it exists and the fake one otherwise 
      .Join(real, l=>l.Year, r=>r.Year, (l,r) => r == null ? l : r); 

इससे आपको इच्छित परिणाम सेट का उत्पादन होगा। आपको सूची आइटमों के लिए नामित प्रकार को परिभाषित करने की आवश्यकता होगी, हालांकि, दो अलग-अलग परिभाषित अनाम प्रकारों को पूर्ण रूप से रूपांतरित नहीं किया जा सकता है, भले ही उनके पास सभी सदस्य प्रकार/नाम हों।

1

IEnumerable.Union और IEqualityComparer का उपयोग करना।

पीएस यदि वास्तविक सूची में अधिक तत्व होते हैं (वर्षों जो नकली सूची में मौजूद नहीं होते हैं) के बावजूद बाएं जुड़ने की तुलना में इसका परिणाम अलग-अलग परिणाम होगा। बाएं जुड़ने से उन परिणामों को वापस नहीं किया जाएगा जो वांछित परिणाम हो सकते हैं (ओपी से स्पष्ट नहीं)।

public class MyClass 
{ 
    public int ID {get; set;} 
    public int Year {get; set;} 
    public string X {get; set;} 
} 

public class MyClassEqualityComparer : IEqualityComparer<MyClass> 
{ 
    public bool Equals(MyClass x, MyClass y) 
    { 
     return x.Year == y.Year; 
    } 

    public int GetHashCode(MyClass obj) 
    { 
     return obj.ToString().ToLower().GetHashCode(); 
    } 
} 

void Main() 
{ 
    var fake = new List<MyClass> { 
      new MyClass { ID = 1, Year = 2011, X = "" } 
     , new MyClass { ID = 2, Year = 2012, X = "" } 
     , new MyClass { ID = 3, Year = 2013, X = "" } 
    }; 

    var real = new List<MyClass> { 
      new MyClass { ID = 35, Year = 2011, X = "Information" } 
     , new MyClass { ID = 77, Year = 2013, X = "Important" } 
    }; 

    var merged = real.Union(fake, new MyClassEqualityComparer()); 
} 
संबंधित मुद्दे