2012-11-21 10 views
8

Sto solo cercando di ritornare vero se una lista contiene qualsiasi del nome/valore da lista2:Controllare se una lista contiene tutti gli elementi di un altro

Questa sarebbe la mia struttura:

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>(); 

Questo dovrebbe restituire true:

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

Ma questo sarebbe tornato falso perché Nome & & Valore non corrispondono:

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

Ogni elenco potrebbe contenere molti valori diversi e ho solo bisogno di sapere se uno qualsiasi di Elenco1 corrisponde a uno in List2.

Ho provato con:

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

ma questo sembra restituire false in tutti i casi, io parto dal presupposto che questo è perché ho in mano una classe in List, piuttosto che una semplice int/string?

+6

'Intersect' funziona su riferimenti per impostazione predefinita, in quanto si crea un nuovo oggetto ogni volta, che avrebbe dovuto scrivere il proprio [' IEqualityComparer '] (http://msdn.microsoft.com /en-us/library/ms132151.aspx) –

risposta

7

Override Equals e GetHashCode implementazione per la classe:

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(); 
    } 
} 

Oppure creare un operatore di confronto per Intersect funzione.

+0

Ho provato questo subito dopo aver postato la domanda qui e ha funzionato. Segnalo come risposta quando sono autorizzato poiché è lo stesso della mia soluzione. Grazie. – webnoob

+0

@webnoob siete i benvenuti. Il problema era nelle implementazioni di default 'Equals' e' GetHashCode', che usano riferimenti a oggetti per confrontare oggetti diversi. E Linq usa questi metodi per il confronto. –

5

Considerato il rendimento non ha importanza:

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

Alternative sarebbe quello di ignorare Equals o per renderlo una struttura (probabilmente non appropriato)

+2

Le prestazioni sono sempre importanti;) – webnoob

1

Il problema qui è che si stanno confrontando i riferimenti e non gli oggetti. Poiché crei ogni volta un nuovo oggetto, gli elenchi non manterranno mai gli stessi riferimenti.

Prova:

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

Questo è quello che pensavo fosse il problema, ora ho implementato un IEqualityComparer per ordinare il problema. – webnoob

+0

Assolutamente. Hai due approcci qui a seconda di ciò che ti serve. Più spesso, vogliamo controllare i riferimenti, ma a volte è sufficiente confrontare i valori. – Pete

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

Ma le prestazioni potrebbero essere cattivo

0

tardi per imbattersi in ma con intersecano possiamo utilizzare selezionare ed evitare di utilizzare l'uguaglianza.

list1.Select(Function(p) p.ItemID).Intersect(list2.Select(Function(p)p.ItemID)).Any() 
Problemi correlati