2011-08-25 15 views
5

primer ejemplo que trabaja:LINQ y 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)); 

Ahora me gustaría utilizar dos listas de objetos como fuente y obtener la lista de objetos que tienen estos mismos valores de identificación de miembro.

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

continuación no se compila:

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

Sé que está mal, pero hacerlo en este orden para una mejor comprensión. Le agradecería que alguien me muestre el camino correcto :-)

Saludos Mariusz

+1

Gracias MDM para editar :-) – Mariusz

+0

Si solo los cambios fueron agradecidos – Baz1nga

Respuesta

3

Se podría hacer que su clase de prueba equatable:

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

Entonces esto funcionaría:

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

Me gusta más esta respuesta porque la expresión lambda aún se ve limpia y legible. Muchas gracias :) – Mariusz

2

enter code here versión simple sería

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

o puede utilizar la versión de LINQ de una combinación interna si no repetir

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

o podría utilizar un 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()); 

finalmente si reemplaza iguales y GetHashCode() en la prueba puede hacerlos comparables

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

nuevo esto permitirá que hagas list1.Intersect(list2) o list2.Intersect(list1)

+0

var query = lista2 .Donde (c => list1.Select (l => l.ID) .Contains (c.ID)) se ve bastante legible y se une usando lambdas simplemente me hace llorar :-) Muchas gracias Bob! – Mariusz

6

puede realizar una inner join como sigue:

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, enfoque mucho mejor. – mdm

+0

Gracias. Funciona de maravilla. Olvidé que la unión filtrará las identificaciones que están a la izquierda o a la derecha solamente. De ahora en adelante (tenemos una intersección en este momento) ¿cómo conseguirías algo así como. Excepto? – Mariusz

+0

@aristo echa un vistazo a la versión final de mi respuesta, puedes simplemente reemplazar la línea de intersección con una línea excepto –

2

Trate

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

Es necesario enumerar la otra colección con su propio código para obtener lo que quiere, porque .Contains utiliza la función .equals, que para los objetos sólo va a coincidir en contra de la referencia .

+0

Ejemplo muy agradable y limpio. Gracias Michael! No sabía que hay tantas maneras de lograr eso :-) – Mariusz

Cuestiones relacionadas