2013-04-02 3 views
30

Mam List<PropA>Znajdź przedmioty z listy, które istnieją w innej listy

PropA 
{ 
    int a; 
    int b; 
} 

i inny List<PropX>

PropX 
{ 
    int a; 
    int b; 
} 

Teraz muszę znaleźć przedmioty z List<PropX> które istnieją w List<PropA> pasujących b właściwość wykorzystująca lambda lub LINQ.

+1

A czego próbowałeś do tej pory? Na to pytanie odpowiedziano już zbyt wiele razy ... – walther

+1

http://code.msdn.microsoft.com/LINQ-Set-Operators-374f34fe –

+0

@David Być może każdy z nich ma inne pola, których nie pokazał, lub mają inny zestaw metod, mimo że mają te same wartości lub z wielu innych powodów. – Servy

Odpowiedz

29

To, co chcesz zrobić, to Join dwie sekwencje. LINQ ma operatora Join który robi dokładnie to:

List<PropX> first; 
List<PropA> second; 

var query = from firstItem in first 
    join secondItem in second 
    on firstItem.b equals secondItem.b 
    select firstItem; 

Zauważ, że operator w LINQ Join jest również napisane bardziej efektywnie wykonać tę operację sporo niż naiwnych wdrożeń, które nie szukaj liniową przez drugi kolekcji dla każdej pozycji.

+7

Istnieje również inny sposób zapisu tego ... 'first.Join (second, f => fb, s => sb, (fir, sec) => fir);' –

+0

@ MalcolmO'Hare Tak, i obie są całkowicie identyczne. To się w to skomplikuje. Zauważyłem, że większość ludzi woli, aby słowo "Join" było wypisywane przy użyciu składni zapytania w stosunku do składni metody, nawet bardziej niż w przypadku innych metod zapytań. – Servy

+0

W zależności od logiki biznesowej i danych wejściowych, można chcieć dołączyć wywołanie Distinct(), aby usunąć powielone wartości zwracane przez join. –

55
ListA.Where(a => ListX.Any(x => x.b == a.b)) 
+2

Przeprowadziłem prosty test, a wyniki "Join" były * znacznie * szybsze. http://ideone.com/xW1CnL. Będziesz musiał uruchomić kod samodzielnie, aby użyć większego zestawu danych. – Servy

+0

Tak, zapomniałem uruchomić zapytanie. Wydaje się, że w przypadku wystarczająco małego zestawu danych (mniej niż 500 elementów) koszt wdrożenia łączenia przewyższa wzrost wydajności. –

+0

Jeśli wydajność nie wchodzi w rachubę, wtedy wziąłbym prostotę kodu. Byłoby to subiektywne i osobiste preferencje. –

19
var commonNumbers = first.Intersect(second); 

Daje to wspólne wartości między dwiema listami, znacznie szybsze i czystsze podejście, a następnie dołączenie lub inne wyrażenia Lambda.

Po prostu spróbuj.

Źródło: MSDN

+7

Działa to tylko wtedy, gdy 'T' byłby tego samego typu dla zbiorów' IEnumerable ', co nie jest prawdą w zadawanym pytaniu. – Daniel

4

Dobrze wszystko powyżej nie będzie działać, jeśli masz wiele parametrów, więc myślę, że jest to najlepszy sposób, aby to zrobić.

Na przykład: Znajdź niesparowane produkty ze zwierząt domowych i zwierząt domowych2.

var notMatchedpets = pets 
    .Where(p2 => !pets2 
    .Any(p1 => p1.Name == p2.Name && p1.age == p2.age)) 
    .ToList();