2010-11-01 10 views
5

क्या दो सूचीओं के लिए Except() का उपयोग करना संभव है जिसमें दो अलग-अलग वर्ग हैं लेकिन एक सामान्य क्षेत्र है? मेरे पास List<User1> और List<User2> संग्रह हैं। आईडी कॉलम को छोड़कर उनके पास अलग-अलग गुण हैं और मैं इस आईडी कॉलम का उपयोग करके उनके बीच अलग-अलग रिकॉर्ड ढूंढना चाहता हूं। मैं List<>.Except() उपयोग करने के लिए कोशिश कर रहा हूँ, लेकिन मैं इस त्रुटि हो रही है:IEnumerable.Except() एक सामान्य फ़ील्ड के साथ विभिन्न वर्गों के बीच

The type arguments for method 'System.Linq.Enumerable.Except(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

यहाँ मैं क्या कोशिश कर रहा हूँ है:

List<User1> list1 = List1(); 
List<User2> list2 = List2(); 
var listdiff = list1.Except(list2.Select(row => row.Id)); 

क्या मैं गलत कर रहा हूँ?

उत्तर

9

सूची 1 में उपयोगकर्ता 1 और सूची 2 के उदाहरण उपयोगकर्ता 2 के उदाहरण हैं।

list1.Except(list2.Select(row => row.Id)) द्वारा किस प्रकार का उदाहरण बनाया जाना चाहिए? दूसरे शब्दों में यदि टाइप अनुमान उपलब्ध नहीं था, तो आप var को किस स्थान से बदल देंगे?

यदि उपयोगकर्ता 1 और उपयोगकर्ता 2 उसी पूर्वजों (आईडी के साथ) से प्राप्त होता है, तो इसके बजाय List<User> का उपयोग करें।

अन्यथा

:

var list2Lookup = list2.ToLookup(user => user.Id); 
var listdiff = list1.Where(user => (!list2Lookup.Contains(user.Id)) 
+1

+1 उपयोग कर रहा हूँ अगर आप '' बजाय list1' की list2' पर देखने बनाना भूल गया की कोशिश करो। या लुकअप के बिना 'var listdiff = list1.Where (user =>! (List2.Any (user2 => user2.Id == user.Id)); ' –

+0

Yup ने देखा कि कुछ मिनट पहले गलती –

+0

+1: अच्छी चीजें भी काफी कुशल होंगी। – Ani

3

संक्षेप में, सूचियां List<object> बनें और .NET 4.0: dynamic से C# सुविधा का उपयोग करें।

उदाहरण:

var listDiff = list1 
    .AsEnumerable<object>() 
    .Except(list2 
     .AsEnumerable<object>() 
     .Select(row => ((dynamic)row).ID)); 
+0

क्षमा करें जोड़ने के लिए है कि मैं v3.5 – dstr

2

तुम सिर्फ list1 में Ids कि list2 में नहीं हैं, आप कर सकते हैं चाहते हैं:

var idsInList1NotInList2 = list1.Select(user1 => user1.Id) 
           .Except(list2.Select(user2 => user2.Id)); 

आप भी जुड़े User1 वस्तुओं की जरूरत है, यहाँ एक ही रास्ता है (मानते हैं कि आईडी 1 उपयोगकर्ता 1 ऑब्जेक्ट के लिए अद्वितीय हैं):

// Create lookup from Id to the associated User1 object 
var user1sById = list1.ToDictionary(user1 => user1.Id); 

// Find Ids from the lookup that are not present for User2s from list2 
// and then retrieve their associated User1s from the lookup 
var user1sNotInList2 = user1sById.Keys 
           .Except(list2.Select(user2 => user2.Id)) 
           .Select(key => user1sById[key]); 

संपादित करें: इस विचार पर vc74 का लेना थोड़ा बेहतर है; यह विशिष्टता की आवश्यकता नहीं है।

4

नहीं Except, लेकिन सही परिणाम और इसी तरह के प्रदर्शन:

// assumes that the Id property is an Int32 
var tempKeys = new HashSet<int>(list2.Select(x => x.Id)); 
var listdiff = list1.Where(x => tempKeys.Add(x.Id)); 

और, ज़ाहिर है, आप यह सब अपने खुद के फिर से प्रयोग करने योग्य विस्तार विधि में लपेट कर सकते हैं :

var listdiff = list1.Except(list2, x => x.Id, y => y.Id); 

// ... 

public static class EnumerableExtensions 
{ 
    public static IEnumerable<TFirst> Except<TFirst, TSecond, TKey>(
     this IEnumerable<TFirst> first, 
     IEnumerable<TSecond> second, 
     Func<TFirst, TKey> firstKeySelector, 
     Func<TSecond, TKey> secondKeySelector) 
    { 
     // argument null checking etc omitted for brevity 

     var keys = new HashSet<TKey>(second.Select(secondKeySelector)); 
     return first.Where(x => keys.Add(firstKeySelector(x))); 
    } 
} 
2
public static IEnumerable<TSource> Except<TSource, CSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> TSelector, IEnumerable<CSource> csource, Func<CSource, TKey> CSelector) 
    { 
     bool EqualFlag = false; 
     foreach (var s in source) 
     { 
      EqualFlag = false; 
      foreach (var c in csource) 
      { 
       var svalue = TSelector(s); 
       var cvalue = CSelector(c); 
       if (svalue != null) 
       { 

        if (svalue.Equals(cvalue)) 
        { 
         EqualFlag = true; 
         break; 
        } 
       } 
       else if (svalue == null && cvalue == null) 
       { 
        EqualFlag = true; 
        break; 
       } 
      } 
      if (EqualFlag) 
       continue; 
      else 
      { 
       yield return s; 
      } 
     } 

    } 
0

list1.Where(user1 => !list2.Any(user2 => user2.Id.Equal(user1.Id))); 
+0

[इसलिए] में आपका स्वागत है! यह क्यों काम करता है? जो लोग स्वयं के लिए उस प्रश्न का उत्तर दे सकते हैं उन्हें शायद किसी और के कोड की आवश्यकता नहीं है। – jpaugh

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