我正在使用LINQ進行學習,可是當我沒有簡單的列表時(我很容易作到簡單的整數列表,這不是問題),我沒法弄清楚如何使用Distinct。 若是要在對象的一個或多個屬性的對象列表上使用Distinct ,該怎麼辦? web
示例:若是一個對象是Person
,具備Property Id
。 如何獲取全部Person並在其上使用Distinct
和對象的屬性Id
? 學習
Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1" Person3: Id=2, Name="Test2"
我怎樣才能獲得Person1和Person3? 那可能嗎? 測試
若是LINQ沒法實現,那麼根據.NET 3.5中Person
某些屬性來獲取Person
列表的最佳方法是什麼? 網站
如下代碼在功能上等同於Jon Skeet的答案 。 this
在.NET 4.5上進行了測試,能夠在任何早期版本的LINQ上運行。 google
public static IEnumerable<TSource> DistinctBy<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { HashSet<TKey> seenKeys = new HashSet<TKey>(); return source.Where(element => seenKeys.Add(keySelector(element))); }
偶然地, 在Google Code上查看Jon Skeet的DistinctBy.cs最新版本 。 spa
若是須要在多個屬性上使用Distinct方法,則能夠簽出個人PowerfulExtensions庫。 當前它還處於起步階段,可是您已經能夠在許多屬性上使用Distinct,Union,Intersect,Except等方法。 code
這是您的用法: 對象
using PowerfulExtensions.Linq; ... var distinct = myArray.Distinct(x => x.A, x => x.B);
與其餘.NET版本兼容的最佳方法是重寫Equals和GetHash來處理此問題(請參閱Stack Overflow問題。 此代碼返回不一樣的值。可是,我要返回的是強類型集合,而不是匿名類型 ),可是若是您須要在整個代碼中使用通用的東西,那麼本文中的解決方案很是有用。 blog
當咱們在項目中面對這樣的任務時,咱們定義了一個小的API來構成比較器。
所以,用例是這樣的:
var wordComparer = KeyEqualityComparer.Null<Word>(). ThenBy(item => item.Text). ThenBy(item => item.LangID); ... source.Select(...).Distinct(wordComparer);
API自己以下所示:
using System; using System.Collections; using System.Collections.Generic; public static class KeyEqualityComparer { public static IEqualityComparer<T> Null<T>() { return null; } public static IEqualityComparer<T> EqualityComparerBy<T, K>( this IEnumerable<T> source, Func<T, K> keyFunc) { return new KeyEqualityComparer<T, K>(keyFunc); } public static KeyEqualityComparer<T, K> ThenBy<T, K>( this IEqualityComparer<T> equalityComparer, Func<T, K> keyFunc) { return new KeyEqualityComparer<T, K>(keyFunc, equalityComparer); } } public struct KeyEqualityComparer<T, K>: IEqualityComparer<T> { public KeyEqualityComparer( Func<T, K> keyFunc, IEqualityComparer<T> equalityComparer = null) { KeyFunc = keyFunc; EqualityComparer = equalityComparer; } public bool Equals(T x, T y) { return ((EqualityComparer == null) || EqualityComparer.Equals(x, y)) && EqualityComparer<K>.Default.Equals(KeyFunc(x), KeyFunc(y)); } public int GetHashCode(T obj) { var hash = EqualityComparer<K>.Default.GetHashCode(KeyFunc(obj)); if (EqualityComparer != null) { var hash2 = EqualityComparer.GetHashCode(obj); hash ^= (hash2 << 5) + hash2; } return hash; } public readonly Func<T, K> KeyFunc; public readonly IEqualityComparer<T> EqualityComparer; }
更多詳細信息,請訪問咱們的網站: LINQ中的IEqualityComparer 。
您可使用標準的Linq.ToLookup()
。 這將爲每一個惟一鍵建立一個值集合。 只需選擇集合中的第一項
Persons.ToLookup(p => p.Id).Select(coll => coll.First());