2013-04-02 15 views
30

Ho un List<PropA>Trova elementi da un elenco che esistono in un altro elenco

PropA 
{ 
    int a; 
    int b; 
} 

e un altro List<PropX>

PropX 
{ 
    int a; 
    int b; 
} 

ora devo trovare prodotti di List<PropX> che esistono in List<PropA> corrispondenti b proprietà utilizzando lambda o LINQ.

+1

E che cosa hai provato finora? Questa domanda ha avuto risposta già troppe volte ... – walther

+1

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

+0

@David Forse ognuno di essi ha campi diversi che non ha mostrato, o hanno un diverso insieme di metodi anche se hanno gli stessi valori o un numero qualsiasi di altri motivi. – Servy

risposta

29

Quello che vuoi fare è Join le due sequenze. LINQ ha un operatore di Join che fa esattamente questo:

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

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

Nota che l'operatore Join in LINQ è scritto anche per eseguire questa operazione un po 'più efficiente rispetto alle implementazioni ingenui che avrebbe fatto una ricerca lineare attraverso la seconda raccolta per ogni oggetto.

+7

C'è anche l'altro modo di scrivere questo ... 'first.Join (second, f => fb, s => sb, (fir, sec) => fir);' –

+0

@ MalcolmO'Hare Sì, ed entrambi sono completamente identici. Questo si compilerà in questo. Ho scoperto che la maggior parte delle persone preferisce che "Join" venga scritto usando la sintassi della query sulla sintassi del metodo, anche più di altri metodi di query. – Servy

+0

A seconda di come avvengono la logica di business e i dati di input, è possibile includere una chiamata Distinct() per rimuovere i valori duplicati restituiti dal join. –

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

Bene, ho eseguito un semplice test ed i risultati di un 'Join' erano * sostanzialmente * più veloci. http://ideone.com/xW1CnL. Dovrai eseguire il codice da solo per utilizzare un set di dati più ampio. – Servy

+0

Sì, ho dimenticato di eseguire la query. Sembra che per un set di dati abbastanza piccolo (meno di 500 articoli), il costo dell'istanziazione di join superi il guadagno in termini di prestazioni. –

+0

Se la prestazione è fuori discussione, prenderei la semplicità del codice. Questa sarebbe una preferenza soggettiva e personale. –

19
var commonNumbers = first.Intersect(second); 

Questo vi darà i valori comuni tra due elenchi, molto più veloce e approccio più pulito quindi unire o altre espressioni Lambda.

Basta provarlo.

Fonte: MSDN

+7

Funzionerebbe solo se 'T' era lo stesso tipo per entrambi gli insiemi' IEnumerable ', che non è il caso nella domanda posta. – Daniel

4

Bene tutto di cui sopra non funziona se si dispone di più parametri, quindi penso che questo sia il modo migliore per farlo.

Ad esempio: Trova elementi non abbinati da animali domestici e animali domestici2.

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