2010-03-04 89 views
40

如果我有一个IEnumerable,其中ClassA公开一个类型为long的ID属性。 是否有可能使用Linq查询来获取属于第二个IEnumerable的ID的ClassA的所有实例?相交LINQ查询

换句话说,这可以做到吗?

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()的ID或对结果或GroupJoin替换Join(该参数到GroupJoin将是相同的)。

+0

这就是我一直在寻找,谢谢。不知何故,这并没有使我在原来的问题,但idsToFind = IEnumerable 。 再次感谢。 – 2010-03-04 18:00:13

+1

任何有关'original'或'idsToFind'大小的'Join'开始比'Where'/'Contains'解决方案更有效的想法吗?我可以想象,对于小列表(可能20-30项),“Join”的开销太多了? – Tobias 2012-09-05 09:00:45

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的元素。如果你正在寻找只是一个ID的列表,你可以做这需要的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(); 
     } 
    } 

其次,我们应用KeyEqualityComparerIntersect功能:

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