2012-10-10 19 views
-1

我有兩個List實例,即OldCustomers,NewCustomers。如何聯合使用LINQ的列表<T>?

List<Customer> OldCustomers; 

List<Customer> NewCustomers; 

我只想要舊客戶,新客戶的聯盟。也就是說,如果CustomerID 100存在於OldCustomerList中,並且也存在於NewCustomer List中,則OldCustomer List中的Customer Details必須被刪除,並且NewCustomer List必須放置在結果列表中,如下所示。

List<Customer> NewCustomers; 
    Union 
List<Customer> OldCustomers; 

我該如何在LINQ中做到這一點?

由於事先

+0

你試過了'Union'方法?爲什麼它不工作? – jeroenh

回答

0

可以使用聯盟功能,這樣

sequence1.Union(sequence2) 

var custlist = NewCustomers.Union(OldCustomers).ToList(); 

閱讀:Enumerable.Union Method (IEnumerable, IEnumerable)

例子:

  int[] ints1 = { 5, 3, 9, 7, 5, 9, 3, 7 }; 
      int[] ints2 = { 8, 3, 6, 4, 4, 9, 1, 0 }; 

      IEnumerable<int> union = ints1.Union(ints2); 

      foreach (int num in union) 
      { 
       Console.Write("{0} ", num); 
      } 

      /* 
      This code produces the following output: 

      5 3 9 7 8 6 4 1 0 
      */ 
0

您可以使用Union

var union = NewCustomers.Union(OldCustomers); 

,也許你將不得不實現自己的comparerCustomer

0

Union會比較Customer對象的情況下(如果不使用IEqualityComparer)。我認爲你正在尋找的東西像UnionBy

var finalList = NewCustomers.Concat(OldCustomers) 
        .GroupBy(x => x.CustomerID) 
        .Select(x => x.First()) 
        .ToList(); 

- 編輯 -

一種可能UnionBy實現:

var finalList = NewCustomers.UnionBy(OldCustomers, c => c.CustomerID).ToList(); 

-

public static class SOExtension 
{ 

    public static IEnumerable<T> UnionBy<T,V>(this IEnumerable<T> list, IEnumerable<T> otherList,Func<T,V> selector) 
    { 
     HashSet<V> set = new HashSet<V>(); 

     foreach (T t in list) 
     { 
      set.Add(selector(t)); 
      yield return t; 
     } 
     foreach(T t in otherList) 
     { 
      if(!set.Contains(selector(t))) 
       yield return t; 
     } 
    } 
} 
1

爲了使用Union ,你必須定製EqualityComparer

public class CusComparer : EqualityComparer<Customer> 
{ 
    public override bool Equals(Customer x, Customer y) 
    { 
     return x.CustomerID == y.CustomerID; 
    } 

    public override int GetHashCode(Customer obj) 
    { 
     return obj.CustomerId.GetHashCode(); 
    } 
} 

然後:

var unionCustomers = NewCustomers.Union(OldCustomers, new CusComparer()); 
+1

您需要在'CustomerID'而不是'obj'上調用'GetHashCode',因爲在檢查'Equals'前檢查'GetHashCode'是否相等。 – Rawling

+0

@Rawling:正確,我的錯誤:)忘記 –

+0

@TimSchmelter:不要假設,試試這個 –

0

所以,你要採取一切新的客戶和所有的老客戶其不在新的清單:

List<Customer> customers = NewCustomers.Concat(OldCustomers.Except(NewCustomers)).ToList(); 

記住落實IEqualityComparer<T>通用界面來比較你的客戶(可能由CustomerID)。因此,您需要爲Customer提供自己的GetHashCodeEquals方法。

這裏是一個可能的實現:

public class Customer 
{ 
    public int CustomerID { get; set; } 
    public string CustomerName { get; set; } 

    public override bool Equals(Object obj) 
    { 
     Customer cust = obj as Customer; 
     if (cust == null) return false; 
     return cust.CustomerID == CustomerID; 
    } 

    public override int GetHashCode() 
    { 
     return CustomerID.GetHashCode(); 
    } 

    public class Comparer : IEqualityComparer<Customer> 
    { 
     public bool Equals(Customer x, Customer y) 
     { 
      if (x == null && y == null) return true; 
      if (x == null || y == null) return false; 
      return x.Equals(y); 
     } 

     public int GetHashCode(Customer obj) 
     { 
      if (obj == null) return -1; 
      return obj.GetHashCode(); 
     } 
    } 
} 

注意,我在Customer覆蓋EqualsGetHashCode。通過這種方式,您甚至不需要將IEqualityComparer<Customer>的實例傳遞給Except(或允許傳遞比較器的任何其他方法)。

但對於完整起見我還添加了一個實現該接口的類Comparer,所以你也可以通過它來除:

NewCustomers.Concat(OldCustomers.Except(NewCustomers, new Customer.Comparer())); 
+0

正如你所評論的那樣:'只有正確執行GetHashCode和Equals才能正確運行' –

+0

編輯提供'Equals '和'GetHashCode'。 –

+0

如果您在Customer類中重寫'Equals'和'GetHashCode',則不需要自定義EqualityComparer,它將使用EqualityComparer 。默認 –

0
HashSet<Customer> set = new HashSet<Customer>(list1); 
set.SymmectricExceptWith(list2); // Or other userful methods.