2013-06-26 13 views
28
का उपयोग

मैं निम्नलिखित है कहते हैं:वाया एक संपत्ति दो सूचियों की तुलना करें LINQ

class Widget1{ 
     public int TypeID { get; set; } 
     public string Color { get; set; } 
    } 

    class Widget2 
    { 
     public int TypeID { get; set; } 
     public string Brand { get; set; } 
    } 

    private void test() 
    { 
     List<Widget1> widgets1 = new List<Widget1>(); 
     List<Widget2> widgets2 = new List<Widget2>(); 
     List<Widget1> widgets1_in_widgets2 = new List<Widget1>(); 

     //some code here to populate widgets1 and widgets2 

     foreach (Widget1 w1 in widgets1) 
     { 
      foreach (Widget2 w2 in widgets2) 
      { 
       if (w1.TypeID == w2.TypeID) 
       { 
        widgets1_in_widgets2.Add(w1); 
       } 
      } 
     } 
    } 

मैं दो foreach उपयोग कर रहा हूँ एक तिहाई सूची को पॉप्युलेट करने के TypeID द्वारा सूचियों की तुलना करने के लिए लूप। क्या टाइपिड के माध्यम से इन दो सूचियों की तुलना करने के लिए LINQ का उपयोग करने का कोई और तरीका है? शायद इंटरस्टेक्ट या कुछ अन्य फ़ंक्शन का उपयोग कर रहे हैं?

उत्तर

33

आप यहां क्या चाहते हैं Join है।

var widgets1_in_widgets2 = from first in widgest1 
    join second in widgets2 
    on first.TypeID equals second.TypeID 
    select first; 

IntersectJoin का एक विशेष मामला है, जहां दो दृश्यों एक ही प्रकार के कर रहे हैं के रूप में की कम या ज्यादा सोचा हो सकता है, और इस प्रकार प्रत्येक प्रकार के लिए एक प्रक्षेपण की आवश्यकता होगी, कुंजी उत्पन्न करने के बजाय समानता के लिए लागू किया जा सकता तुलना करना। आपके मामले को देखते हुए, Intersect एक विकल्प नहीं है।

एक विशेष आईडी अपने दूसरे सेट में दोहराया गया है और आप आइटम परिणाम में दोहराया जा करने के लिए तो आप एक GroupJoin बजाय Join एक के उपयोग कर सकते हैं नहीं करना चाहते हैं:

var widgets1_in_widgets2 = from first in widgest1 
    join second in widgets2 
    on first.TypeID equals second.TypeID 
    into matches 
    where matches.Any() 
    select first; 
+0

+1 _ _ यह एक विकल्प होगा जब एक कस्टम 'IEqualityComparer ' संभव होगा "अपने मामले को देखते हुए, इंटरसेक्ट एक विकल्प नहीं है", तो एक आम आधार प्रकार। फिर आप इसे [इस अधिभार] (http://msdn.microsoft.com/en-us/library/bb355408.aspx) पर पास कर सकते हैं या 'TypeID 'की तुलना में' बेसविड्ज 'में' बराबर '+' GetHashCode' को ओवरराइड कर सकते हैं डिफ़ॉल्ट रूप से। –

3

जुड़ें दोष यह है कि आपके परिणाम डुप्लिकेट किए जा सकते हैं यदि widgets1 या widgets2 में एक से अधिक टाइप आईडी के तत्व होते हैं (जो आपके मूल कोड पर भी लागू होते हैं)।

निम्नलिखित वही करेंगे जो आप चाहते हैं: विजेट्स 1 से सभी तत्व लौटाएं जिसके लिए संबंधित टाइप आईडी वाला तत्व विजेट 2 में मौजूद है।

widgets1_in_widgets2 = (from w1 in widgets1 
         where widgets2.Any(w2 => w1.TypeID == w2.TypeID) 
         select w1).ToList() 
+1

हालांकि यह उचित आउटपुट उत्पन्न करेगा, लेकिन इसके बजाय खराब प्रदर्शन होगा क्योंकि आप किसी अन्य संग्रह में प्रत्येक आइटम के संग्रह पर रैखिक खोज कर रहे हैं। – Servy

+0

'" जॉइन में शामिल होने की कमी है कि आपके परिणाम डुप्लिकेट किए जा सकते हैं यदि विगेट्स 1 या विगेट्स 2 में एक ही टाइपआईड के साथ तत्व एक से अधिक होते हैं। "ओपी में कोड वास्तव में * सटीक * समान आउटपुट 'जॉइन' के रूप में होगा, इसलिए या तो उसके पास किसी भी सूची में डुप्लिकेट कुंजी नहीं है, या वह * डुप्लीकेट परिणाम चाहता है * चाहता है। – Servy

+0

@ सर्वी: अच्छा बिंदु, मैं अपने उत्तर में इसका उल्लेख करूंगा। फिर भी, परिवर्तनीय नामकरण मुझे लगता है कि यह अनजान है। – Heinzi

28

आप क्या कर सकते हैं इस

widgets2.Where(y=>widget1.Any(z=>z.TypeID==y.TypeID)); 
+4

हालांकि यह उचित आउटपुट उत्पन्न करेगा, लेकिन इसके बजाय खराब प्रदर्शन होगा क्योंकि आप किसी अन्य संग्रह में प्रत्येक आइटम के संग्रह पर रैखिक खोज कर रहे हैं। – Servy

+0

@ सर्वी हम्म..इंडिड – Anirudha

+1

परिवर्तनों का सबसे सरल बस 'हैशसेट' में सेटों में से किसी एक के टाइपआईड्स को स्टोर करना है जिसे अधिक तेज़ी से खोजा जा सकता है। जैसा कि मैंने दिखाया है, केवल 'जॉइन' का उपयोग करना एक और महत्वपूर्ण परिवर्तन होगा, हालांकि यह हुड के नीचे एक ही चीज़ को बहुत अधिक कर देगा। – Servy

2

का अधिभार उपयोग करने का प्रयास मैं इस समाधान "कहाँ"

var isMatch = !widgets1.Where((w1, index) => w1.TypeId == widgets2[index].TypeId)).Any(); 
+1

केवल कोड और कोई स्पष्टीकरण वाला उत्तर नहीं, खासकर जब – ItamarG3

+0

से पहले प्रश्न का पूरी तरह उत्तर दिया गया है, तो आप यह जवाब निर्दिष्ट कर सकते हैं कि यह अलग कैसे है। मुझे यह मामला एक सहायक प्रस्तावित समाधान माना जाता है जहां आप आदेश की तुलना करना चाहते हैं और किसी भी रैखिक खोज से बचें। – DannyMeister

0

चाहते क्योंकि यह आसान है कोड में पढ़ने के लिए।

bool result = firstList.All(o => secondList.Any(w => w.Prop1 == o.Prop1 && w.Prop2 == o.Prop2)); 

बेला में पूर्ण उदाहरण देखें: Fiddle example comparation

+0

Thx, यह मेरे लिए काम किया। अगर (projectIds.All (y => r.ProjectsId.Any (z => z.Equals (y))) { रिपोर्ट। जोड़ें (आर); } – Parveen

संबंधित मुद्दे