2011-08-25 6 views
5

Primo esempio che funziona:Linq e contiene

public class Test 
{ 
    public int ID; 
    public string Name; 
} 

List<int> list1 = Load1(); 
List<Test> list2 = Load2(); 

var query = list2.Where(c => list1.Contains(c.ID)); 

Ora vorrei usare due liste di oggetti come fonte e ottenere l'elenco degli oggetti che hanno questi stessi valori per ID utente.

List<Test> list1 = Load2(); 
List<Test> list2 = Load2(); 

Sotto non compila:

var query = list2.Where(c => **list1.ID.Contains**(c.ID)); 

So che è sbagliato, ma messo qui per una migliore comprensione. Gradirei che qualcuno mi mostrano la strada giusta :-)

saluti Mariusz

+1

Grazie MDM per la modifica :-) – Mariusz

+0

Se solo tutte le modifiche sono state iniziate – Baz1nga

risposta

3

Si potrebbe fare la vostra classe di prova equatable:

public class Test : IEquatable<Test> 
{ 
    public int Id {get;set;} 
    public bool Equals(Test other) 
    { 
    return this.Id == other.Id; 
    } 
} 

Quindi questo dovrebbe funzionare:

list1.Where(item => list2.Contains(item)); 
+0

Questa risposta mi piace di più perché l'espressione lambda sembra ancora pulita e leggibile. Grazie mille :) – Mariusz

2

enter code here versione semplice sarebbe

var query = list2.Where(c=> list1.Select(l=>l.ID).Contains(c.ID)) 

Oppure si potrebbe utilizzare la versione LINQ di un inner join se si avere nessuna ripetizione

var query = list2.Join(list1,a=>a.ID,b=>b.ID,(a,b)=>a); 

o si potrebbe usare uno System.Collections.Generic.IEQualityComparer

public class TestComparerer : IEqualityComparer<Test> { 
    bool IEqualityComparer<Test>.Equals(Test a, Test b) { 
     return a!=null && b!=null && a.ID.Equals(b.ID); 
    } 

    int IEqualityComparer<Test>.GetHashCode(Test a){ 
    return a.ID.GetHashCode(); 
    } 
} 

var query = list2.intersect(list1,new TestComparer()); 

Infine, se si ignora Equals e GetHashCode() in prova è possibile renderli comparabili

public override bool Equals(object o) { 
var other=o as Test; 
return other!=null && this.ID==other.ID; 
} 

public override int GetHashCode() { 
return ID.GetHashCode(); 
} 

di nuovo questo vi permetterà di fare list1.Intersect(list2) o list2.Intersect(list1)

+0

var query = lista2 .Where (c => list1.Select (l => l.ID) .Contains (c.ID)) sembra abbastanza leggibile così come i join che usano lambda semplicemente mi fanno piangere :-) Grazie mille Bob! – Mariusz

6

è possibile eseguire un inner join come segue:

var query = from x in list1 
      join y in list2 on x.ID equals y.ID 
      select new { x, y }; 

o

var query = list1.Join(list2, 
         x => x.ID, 
         y => y.ID, 
         (x, y) => new { x, y }); 
+2

+1, approccio molto migliore. – mdm

+0

Grazie. Funziona come un fascino. Ho dimenticato che il join filtrerà gli ID che sono solo a sinistra o a destra. Andando avanti (abbiamo un incrocio al momento) come vorresti ottenere qualcosa di simile. – Mariusz

+0

@aristo dare un'occhiata alla versione finale sulla mia risposta, è sufficiente sostituire la linea intersecare con una riga esclusa –

2

Provate

list2.Where(c => list1.Any(d => d.ID == c.ID)); 

È necessario enumerare questa collezione con il proprio codice per ottenere ciò che si vuole, perché .Contains utilizza la funzione .equals, che per gli oggetti sarà solo corrispondere contro il riferimento .

+0

Esempio molto bello e pulito. Grazie Michele! Non sapevo che ci sono tanti modi per ottenerlo :-) – Mariusz