2013-05-29 15 views
10

Lista1 zawiera pozycje {A, B} i List2 zawiera pozycje {A, B, C}.Używanie Linq, chyba że nie działa tak jak myślałem

Potrzebuję zwrócić {C}, gdy używam Z wyjątkiem rozszerzenia Linq. Zamiast tego wracam {A, B} i jeśli odwracam listy w moim wyrażeniu, wynikiem jest {A, B, C}.

Czy nie rozumiem punktu Z wyjątkiem? Czy istnieje inne rozszerzenie, którego nie używam?

Przeanalizowałem i wypróbowałem wiele różnych stanowisk w tej sprawie bez powodzenia.

var except = List1.Except(List2); //This is the line I have thus far

EDIT: Tak ja porównując prostych obiektów. Nigdy nie używałem IEqualityComparer, było ciekawie się o tym dowiedzieć.

Dziękuję wszystkim za pomoc. Problem polegał na tym, że nie wprowadzano porównania. Połączony post na blogu i przykład poniżej, gdzie są pomocne.

+1

Co dokładnie znajduje się na tych listach? –

+0

Jaki jest typ danych Twoich produktów. Czy to klasa? Ten link może Ci pomóc http://stackoverflow.com/questions/1645891/why-isnt-except-linq-comparing-things-properly-using-iequatable – arunlalam

+0

Są to proste obiekty z kilkoma właściwościami w danym momencie. Przejrzę twój link. – Schanckopotamus

Odpowiedz

10

Jeśli przechowujesz typy odniesienia na liście, musisz się upewnić, że istnieje sposób porównania obiektów dla równości. W przeciwnym razie zostaną sprawdzone przez porównanie, jeśli odnoszą się do tego samego adresu.

Możesz zaimplementować IEqualityComparer<T> i wysłać go jako parametr do funkcji Except(). Oto pomocna blog post.

+0

Dla jasności jest to rozwiązanie, które rozwiązało mój problem dawno temu i jest realną opcją, w zależności od scenariusza. – Schanckopotamus

6

Po prostu myliłeś kolejność argumentów. Mogę zobaczyć, gdzie to zamieszanie powstało, ponieważ official documentation nie jest tak pomocny jak to może być:

Produkuje nastawioną różnicę dwóch sekwencji za pomocą porównywarka równości domyślny do porównywania wartości.

Jeśli nie jesteś biegły w teorii mnogości, to może nie być jasne, co właściwie jest — set difference to nie jest po prostu to, co różni się pomiędzy seriami. W rzeczywistości Except zwraca listę elementów w pierwszym zestawie, które nie znajdują się w drugim zestawie.

Spróbuj tego:

var except = List2.Except(List1); // { C } 
+0

Jeśli zmienisz kolejność list, otrzymam {A, B, C} – Schanckopotamus

4

Więc po prostu dla zasady ...

// Except gives you the items in the first set but not the second 
    var InList1ButNotList2 = List1.Except(List2); 
    var InList2ButNotList1 = List2.Except(List1); 
// Intersect gives you the items that are common to both lists  
    var InBothLists = List1.Intersect(List2); 

Edycja: Ponieważ Twoje listy zawierają obiekty trzeba przejść w IEqualityComparer dla swojej klasy ... Tutaj to, co będzie wyglądało tylko z próbką IEqualityComparer na podstawie gotowych obiektów ... :)

// Except gives you the items in the first set but not the second 
     var equalityComparer = new MyClassEqualityComparer(); 
     var InList1ButNotList2 = List1.Except(List2, equalityComparer); 
     var InList2ButNotList1 = List2.Except(List1, equalityComparer); 
// Intersect gives you the items that are common to both lists  
     var InBothLists = List1.Intersect(List2); 

public class MyClass 
{ 
    public int i; 
    public int j; 
} 

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

    public int GetHashCode(MyClass obj) 
    { 
     unchecked 
     { 
      if (obj == null) 
       return 0; 
      int hashCode = obj.i.GetHashCode(); 
      hashCode = (hashCode * 397)^obj.i.GetHashCode(); 
      return hashCode; 
     } 
    } 
} 
+0

InList1ButNotList2 daje {C, B, A}, co właśnie się dzieje. – Schanckopotamus

+0

@Schanckopotomus Ahh ... twoje listy są obiektami, a ich właściwości są równe, ale obiekty nie są odniesieniem równym prawu? – Kevin

Powiązane problemy