2010-03-04 5 views
40

Если у меня есть IEnumerable, где ClassA предоставляет свойство ID типа long. Можно ли использовать запрос Linq для получения всех экземпляров ClassA с идентификатором, принадлежащим второму IEnumerable?Intersect LINQ query

Другими словами, это можно сделать?

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

где оригинал является IEnumerable<ClassA> и idsToFind является IEnumerable<long>.

ответ

50

Да.

Как и другие люди, вы можете использовать Where, но это будет крайне неэффективно для больших комплектов.

Если производительность является проблемой, вы можете позвонить Join:

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

Если idsToFind может содержать дубликаты, вам нужно либо вызвать Distinct() на идентификаторы или по результатам или заменить Join с GroupJoin (The параметры для GroupJoin будут одинаковыми).

+0

Это то, что я искал, спасибо. Так или иначе, это не делало это в моем первоначальном вопросе, но idsToFind = IEnumerable . Еще раз спасибо. –

+1

Любая идея, при которой размер 'original' или' idsToFind' 'Join' начинает становиться более эффективным, чем решение' Where'/'Contains'? Я могу себе представить, что для небольших списков (возможно, 20-30 позиций) у 'Join' слишком много накладных расходов? – Tobias

1

Используйте метод Where для фильтрации результатов:

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

Простой способ будет:

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

Вы можете сделать это, но в нынешней форме, вы хотели бы использовать Where способ расширения.

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

Intersect с другой стороны будет найти элементы, которые в обоих IEnumerable-х годах. Если вы ищете просто список идентификаторов, вы можете сделать следующее, который использует преимущества Intersect

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

Я отправлю ответ, используя Intersect.

Это полезно, если вы хотите пересечь 2 IEnumerables того же типа.

Сначала нам потребуется 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(); 
     } 
    } 

Во-вторых, мы применяем KeyEqualityComparer функции Intersect:

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