本文共 4389 字,大约阅读时间需要 14 分钟。
**Linq 的distinct 常用于對數組、集合的去重操作。** **一、對于數值型數組或集合去重直接Distinct()就可以。** new List () { 1, 2, 3, 4, 3, 2 }.Distinct().ToList().ForEach(o => Console.WriteLine(o)); **二、對于自定義類型的集合,直接Distinct往往得不到我們想要的結果** //例子: public class Food { public int foodId { get; set; } public string foodName { get; set; } public override string ToString() { return string.Format("{0}\t{1}", foodId.ToString(), foodName.ToString()); } } private ListFoodInit() { List fl = new List (); fl.Add(new Food { foodId = 1, foodName = "rice" }); fl.Add(new Food { foodId = 2, foodName = "noodle" }); fl.Add(new Food { foodId = 1, foodName = "rice" }); return fl; } //調用: FoodInit().Distinct().ToList().ForEach(o => Console.WriteLine(o)); //結果: //1 rice //2 noodle //1 rice ******//解決方法:****** **//方法1. 使用匿名類** FoodInit().Select(o => new { id = o.foodId, name = o.foodName }).Distinct().ToList().ForEach(o => Console.WriteLine(o)); //結果: //{ id = 1, name = rice } //{ id = 2, name = noodle } **//方法2. 重寫自定義類的Equals,GetHashCode方法**** public class Food : IEquatable { public int foodId { get; set; } public string foodName { get; set; } public override string ToString() { return string.Format("{0}\t{1}", foodId.ToString(), foodName.ToString()); } public bool Equals(Food obj) { if (obj == null || GetType() != obj.GetType()) return false; Food foodItem = obj as Food; return (foodItem.foodId == this.foodId); //規則可以按具體需要,例如 ID 一樣則視為相等 } public override int GetHashCode() { return foodId.GetHashCode(); //注意:按自定義的規則,HashCode相同,才會再去比較 Equals } } //調用 FoodInit().Distinct().ToList().ForEach(o => Console.WriteLine(o)); //結果: //1 rice //2 noodle **//我們可參考 MSDN 上的例子** public class Product : IEquatable { public string Name { get; set; } public int Code { get; set; } public bool Equals(Product other) { //Check whether the compared object is null. if (Object.ReferenceEquals(other, null)) return false; //Check whether the compared object references the same data. if (Object.ReferenceEquals(this, other)) return true; //Check whether the products' properties are equal. return Code.Equals(other.Code) && Name.Equals(other.Name); } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public override int GetHashCode() { //Get hash code for the Name field if it is not null. int hashProductName = Name == null ? 0 : Name.GetHashCode(); //Get hash code for the Code field. int hashProductCode = Code.GetHashCode(); //Calculate the hash code for the product. return hashProductName ^ hashProductCode; } } **// 方法3: 實現類的IEqualityComparer接口** public class Compare : IEqualityComparer { public bool Equals(Food x, Food y) { return x.foodId == y.foodId;//可以自定义去重规则,此处将FoodId相同的就相等 } public int GetHashCode(Food obj) { return obj.foodId.GetHashCode();//注意,按自定義去重規則 } } //調用: FoodInit().Distinct(new Compare()).ToList().ForEach(s => Console.WriteLine(s.ToString())); //結果: //1 rice //2 noodle **//但這樣仍不方便,每個自定義類都需要去寫。我們可以寫一個通用的DISTINCT擴展方法**** public static class DistinctExtensions { public class CommonEqualityComparer : IEqualityComparer { private Func keySelector; public CommonEqualityComparer(Func keySelector) { this.keySelector = keySelector; } public bool Equals(T x, T y) { return EqualityComparer .Default.Equals(keySelector(x), keySelector(y)); } public int GetHashCode(T obj) { return EqualityComparer .Default.GetHashCode(keySelector(obj)); } } public static IEnumerable Distinct (this IEnumerable source, Func keySelector) { return source.Distinct(new CommonEqualityComparer (keySelector)); } } //調用 FoodInit().Distinct(p => p.foodId).ToList().ForEach(o => Console.WriteLine(o)); 或 FoodInit().Distinct(p => p.foodName).ToList().ForEach(o => Console.WriteLine(o)); //結果 //1 rice //2 noodle
转载地址:http://aimdi.baihongyu.com/