2010-03-04 5 views
40

Si j'ai un IEnumerable où ClassA expose une propriété ID de type long. Est-il possible d'utiliser une requête Linq pour obtenir toutes les instances de ClassA avec ID appartenant à une seconde IEnumerable?Intersection requête LINQ

En d'autres termes, cela peut-il être fait?

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

lorsque l'original est un IEnumerable<ClassA> et idsToFind est IEnumerable<long>.

Répondre

50

Oui.

Comme d'autres personnes ont répondu, vous pouvez utiliser Where, mais il sera extrêmement inefficace pour les grands ensembles.

Si la performance est une préoccupation, vous pouvez appeler Join:

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

Si idsToFind peut contenir des doublons, vous devrez soit appeler Distinct() sur les ID ou sur les résultats ou remplacer Join avec GroupJoin (Le les paramètres de GroupJoin seraient les mêmes).

+0

C'est ce que je cherchais, je vous remercie. D'une certaine manière, cela ne l'a pas fait dans ma question originale mais idsToFind = IEnumerable . Merci encore. –

+1

Une idée à quelle taille de 'original' ou' idsToFind' le 'Join' commence à devenir plus efficace que la solution' Where'/'Contains'? Je peux imaginer que pour les petites listes (peut-être 20-30 articles) le 'Join 'a trop de frais généraux? – Tobias

1

Utilisez la méthode Where pour filtrer les résultats:

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

Une façon simple serait:

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

Vous pouvez le faire, mais sous la forme actuelle, vous voudriez utiliser la méthode d'extension Where.

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

Intersect d'autre part trouveront des éléments qui sont dans les deux IEnumerable « s. Si vous cherchez juste une liste des années ID, vous pouvez effectuer les opérations suivantes qui profite de Intersect

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

Je vais poster une réponse en utilisant Intersect.

Ceci est utile si vous souhaitez croiser 2 IEnumerables du même type.

D'abord nous aurons besoin d'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(); 
     } 
    } 

Deuxièmement, nous appliquons les KeyEqualityComparer à la fonction Intersect:

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