2010-09-08 18 views
6

mam 2 lista zbiorów w moim C# app..A i B.użyciu LINQ nie równa

Oba zbiory mieć obiekt klienta, który ma Identyfikator i nazwisko attributes.Typically, A ma więcej elementów niż B.

Korzystając z Linq, chcę zwrócić tylko tych klientów, których identyfikator znajduje się w A, ale nie w B.

Jak to zrobić?

+0

Co masz na myśli mówiąc "join na zasadzie nie równa się stan"? –

+0

może sprawić, że twoje pytanie będzie trochę bardziej szczegółowe? – FosterZ

Odpowiedz

18

Istnieje wiele podejść do podjęcia. Najczystszym podejściem jest użycie metody rozszerzania Except, jeśli nadpisałeś Equals i GetHashCode. Jeśli nie, istnieją inne opcje.

// have you overriden Equals/GetHashCode? 
IEnumerable<Customer> resultsA = listA.Except(listB); 

// no override of Equals/GetHashCode? Can you provide an IEqualityComparer<Customer>? 
IEnumerable<Customer> resultsB = listA.Except(listB, new CustomerComparer()); // Comparer shown below 

// no override of Equals/GetHashCode + no IEqualityComparer<Customer> implementation? 
IEnumerable<Customer> resultsC = listA.Where(a => !listB.Any(b => b.Id == a.Id)); 

// are the lists particularly large? perhaps try a hashset approach 
HashSet<int> customerIds = new HashSet<int>(listB.Select(b => b.Id).Distinct()); 
IEnumerable<Customer> resultsD = listA.Where(a => !customerIds.Contains(a.Id)); 

...

class CustomerComparer : IEqualityComparer<Customer> 
{ 
    public bool Equals(Customer x, Customer y) 
    { 
     return x.Id.Equals(y.Id); 
    } 

    public int GetHashCode(Customer obj) 
    { 
     return obj.Id.GetHashCode(); 
    } 
} 
+0

Dzięki za komentarze ... Z tego wiersza: listA.Where (a =>! ListB.Any (b => b.Id == a.Id)) ;, jak mogę uzyskać trzecią listę "C" który ma te obiekty klienta od A nieobecne w B? – Jimmy

+0

@ Jimmy, 'List listC = listA.Where (a =>! ListB.Any (b => b.Id == a.Id)) ToList();' –

+0

Dzięki Anthony Pegram! Działa to doskonale dla mnie ! Użyłem: listA.Where (a =>! ListB.Any (b => b.Id == a.Id)); podejście. – Jimmy

5

Jeśli korekcja Równa dla obiektu klienta, a potem po prostu korzystać

A.Except(B); 
4

Rozszerzając wyjątkiem, zapewniając swoją równość więc nie trzeba zmienić zachowanie równości. mam to stąd:

http://www.codeproject.com/KB/dotnet/LINQ.aspx#distinct

List<Customer> customersA = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 2, Name = "B" } }; 
List<Customer> customersB = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 3, Name = "C" } }; 

var c = (from custA in customersA 
     select custA.Id).Distinct() 
      .Except((from custB in customersB 
      select custB.Id).Distinct()); 
+0

W tym przypadku, 'var c' będzie" IEnumerable ", reprezentujący sekwencję unikalnych, niedopasowanych identyfikatorów z' customersA'. Aby uzyskać obiekty 'Customer', wynik ten musiałby zostać użyty ponownie w celu wyodrębnienia obiektów z' customersA'. –