2012-11-21 12 views
8

jestem po prostu staramy się zwróci true jeśli lista zawiera którekolwiek z nazwa/wartość z listy2:Sprawdź, czy jedna lista zawiera żadnych elementów z innego

To byłaby moja konstrukcja:

public class TStockFilterAttributes 
{ 
    public String Name { get; set; } 
    public String Value { get; set; } 
} 

List<TStockFilterAttributes> List1 = new List<TStockFilterAttributes>(); 
List<TStockFilterAttributes> List2 = new List<TStockFilterAttributes>(); 

ten należy zwrócić prawdziwe:

List1.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" }); 
List2.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" }); 

ale to return false bo Nazwa & & Wartość nie pasują:

List1.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" }); 
List2.Add(new TStockFilterAttributes { Name = "Foo", Value = "Foo" }); 

Każda lista może zawiera wiele różnych wartości i po prostu trzeba wiedzieć, czy ktoś z listy1 dopasowuje dowolny jeden w lista2.

Próbowałem, używając:

return List1.Intersect(List2).Any(); 

ale wydaje się to return false we wszystkich przypadkach, jestem przy założeniu, to dlatego, że jestem trzyma klasę w liście zamiast prostego INT/ciąg?

+6

'Intersect' działa na odnośnikach domyślnie, ponieważ tworzenie nowego obiektu za każdym razem, trzeba napisać własny [' IEqualityComparer '] (http://msdn.microsoft.com /en-us/library/ms132151.aspx) –

Odpowiedz

7

Zastąp Equals i GetHashCode realizacja dla swojej klasy:

public class TStockFilterAttributes 
{ 
    public String Name { get; set; } 
    public String Value { get; set; } 

    public override bool Equals(object obj) 
    { 
     TStockFilterAttributes other = obj as TStockFilterAttributes; 
     if (obj == null) 
      return false; 

     return Name == obj.Name && Value == obj.Value; 
    } 

    public override int GetHashCode() 
    { 
     return Name.GetHashCode()^Value.GetHashCode(); 
    } 
} 

Albo zapewnić porównywarka do Intersect funkcji.

+0

Próbowałem tego po opublikowaniu pytania tutaj i działało. Zaznaczę to jako odpowiedź, gdy mi wolno, ponieważ jest to to samo co moje rozwiązanie. Dzięki. – webnoob

+0

@webnoob nie ma za co. Problem był w domyślnych implementacjach 'Equals' i' GetHashCode', które wykorzystują odwołania do obiektów do porównywania różnych obiektów. A Linq używa tych metod do porównania. –

5

Zakładając wydajność nie ma znaczenia:

List1.Any(l1 => List2.Any(l2 => l1.Key == l2.Key && l1.Value == l2.Value)); 

Alternatywy byłoby zastąpić równa lub zrobić to struct (prawdopodobnie nie odpowiednie)

+2

Wydajność zawsze ma znaczenie;) – webnoob

1

Problem jest to, że porównujesz odniesienia i nie obiekty. Ponieważ za każdym razem tworzysz nowy obiekt, Listy nigdy nie będą miały tych samych referencji.

Spróbuj:

var FooBar = new TStockFilterAttributes { Name = "Foo", Value = "Bar" }; 
var FooFoo = new TStockFilterAttributes { Name = "Foo", Value = "Foo" }; 
List1.Add(FooBar); 
List2.Add(FooBar); 
List2.Add(FooFoo); 
return List1.Intersect(List2); 
+0

Tak właśnie myślałem, że mam problem, teraz zaimplementowałem IEqualityComparer, aby posortować problem. – webnoob

+0

Absolutnie. Masz dwa podejścia tutaj, w zależności od tego, czego potrzebujesz. Częściej niż nie, chcemy sprawdzić referencje, ale czasami wystarczy porównać wartości. – Pete

3
var query = List1.Where(x => List2.Exists(y => y.Name == x.Name && y.Value == x.Value)); 

Ale wydajność może być złe

0

późno, by zderzyć się z przecinają ale możemy użyć select i unikać równości.

list1.Select(Function(p) p.ItemID).Intersect(list2.Select(Function(p)p.ItemID)).Any() 
Powiązane problemy