2010-03-04 11 views
40

Si tengo un IEnumerable donde ClassA expone una propiedad de ID de tipo long. ¿Es posible usar una consulta de Linq para obtener todas las instancias de ClassA con ID perteneciente a un segundo IEnumerable?Intersecar consulta LINQ

En otras palabras, ¿se puede hacer esto?

IEnumerable<ClassA> = original.Intersect(idsToFind....)? 

donde original es un IEnumerable<ClassA> y idsToFind es IEnumerable<long>.

Respuesta

50

Sí.

Como otras personas han respondido, puede usar Where, pero será extremadamente ineficiente para juegos grandes.

Si el rendimiento es una preocupación, puede llamar Join:

var results = original.Join(idsToFind, o => o.Id, id => id, (o, id) => o); 

Si idsToFind puede contener duplicados, tendrá que llamar a cualquiera de los ID Distinct() ni de los resultados o reemplazar Join con GroupJoin (La los parámetros para GroupJoin serían los mismos).

+0

Esto es lo que estaba buscando, gracias. De alguna manera, esto no lo hizo en mi consulta original, pero idsToFind = IEnumerable . Gracias de nuevo. –

+1

¿Alguna idea de qué tamaño de 'original' o' idsToFind' el 'Join' empieza a ser más eficiente que la solución' Where'/'Contains'? Me imagino que para listas pequeñas (tal vez 20-30 elementos) el 'Join' tiene demasiada sobrecarga? – Tobias

1

utilizar el método de Where para filtrar los resultados:

var result = original.Where(o => idsToFind.Contains(o.ID)); 
5

Una forma sencilla sería:

IEnumerable<ClassA> result = original.Where(a => idsToFind.contains(a.ID)); 
9

usted puede hacerlo, pero en la forma actual, usted querrá usar el método de extensión Where.

var results = original.Where(x => yourEnumerable.Contains(x.ID)); 

Intersect por el contrario se encontrarán elementos que están en ambos IEnumerable 's. Si usted está buscando simplemente una lista de los ID, puede hacer lo siguiente, que se aprovecha de Intersect

var ids = original.Select(x => x.ID).Intersect(yourEnumerable); 
13

Voy a publicar una respuesta usando Intersect.

Esto es útil si desea intersectar 2 IEnumerables del mismo tipo.

En primer lugar vamos a necesitar un EqualityComparer:

public class KeyEqualityComparer<T> : IEqualityComparer<T> 
    { 
     private readonly Func<T, object> keyExtractor; 

     public KeyEqualityComparer(Func<T, object> keyExtractor) 
     { 
      this.keyExtractor = keyExtractor; 
     } 

     public bool Equals(T x, T y) 
     { 
      return this.keyExtractor(x).Equals(this.keyExtractor(y)); 
     } 

     public int GetHashCode(T obj) 
     { 
      return this.keyExtractor(obj).GetHashCode(); 
     } 
    } 

En segundo lugar se aplica la KeyEqualityComparer a la función Intersect:

var list3= list1.Intersect(list2, new KeyEqualityComparer<ClassToCompare>(s => s.Id));