2010-03-04 86 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));