C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重
背景說明
在EF等ORM框架中需要以List實體類的方式對數據進行大量操作,其中免不了對一些數據進行去重復,而C#中IEnumerable.Distinct()便提供了這一功能。只是對剛開始接觸的新人來說比價抽象難以接受,本文會對這一功能進行簡要說明,如果有更好的實現方式,也請大家暢所語言。
在寫本文時,本人也在網上搜索了很多相關資料,其中有幾篇比較有參考價值,也是重點,本文也是基于這幾篇文章提供的代碼進行優化和整理:
1、用泛型委托實現IEqualityComparer接口:https://blog.csdn.net/honantic/article/details/51595823
2、Distinct的多條件查詢:https://blog.csdn.net/lishuangquan1987/article/details/76096022
3、IEqualityComparer中的Equal()和GetHashCode():https://www.cnblogs.com/xiaochen-vip8/p/5506478.html
我們要做的是實現IEqualityComparer()接口,而且必須要用泛型,因為我們希望這個功能是可以對所有實體類實現的。其中對哈希值的了解可以參考第三條鏈接,可以簡單的概括為,哈希值反應的是對象在內存中的地址,只有地址相同的對象才能激活IEqualityComparer中的Equal()方法,Equal()可以根據自己的需求而實現。話不多說,代碼如下:
/// <summary>/// 用委托實現IEqualityComparer<T>接口/// </summary>/// <typeparam name="T">目標類型</typeparam>public class ListComparer<T> : IEqualityComparer<T>{public Func<T, T, bool> EqualsFunc;public Func<T,int> GetHashCodeFunc;public ListComparer(Func<T,T,bool> Equals, Func<T,int> GetHashCode){this.EqualsFunc = Equals;this.GetHashCodeFunc = GetHashCode;}public ListComparer(Func<T, T, bool> Equals) : this(Equals, t => 0){}public bool Equals(T x, T y){if (this.EqualsFunc != null){return this.EqualsFunc(x, y);}else{return false;}}/// <summary>/// 獲取目標對象的哈希值,只有返回相同的哈希值才能運行Equals方法/// </summary>/// <param name="obj">獲取哈希值的目標類型對象</param>/// <returns>返回哈希值</returns>public int GetHashCode(T obj){if (this.GetHashCodeFunc != null){return this.GetHashCodeFunc(obj);}else{return 0;}}}以上代碼中,默認哈希值是相同的,我們開始看看使用效果,代碼如下:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國", City = "北京", Name = "小米" },new Phone { Country = "中國",City = "北京",Name = "華為"},new Phone { Country = "中國",City = "北京",Name = "聯想"},new Phone { Country = "中國",City = "臺北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國",City = "加州",Name = "蘋果"},new Phone { Country = "美國",City = "華盛頓",Name = "三星"}};var Lists = PhoneLists.Distinct<Phone>();foreach (var list in Lists){Console.WriteLine(list.Country + "-" + list.City + "-" + list.Name);}Console.Read();}在Distinct()方法沒有任何參數的情況下,運行后如下圖所示:
我們可以看到,好像并沒有任何效果,但是其實是有效果的,因為每個Phone實體類對象在內存中的地址是不一樣的,? ? ? ? ?Distinct()方法默認篩選出所有內存地址不一樣的實體類對象。
接下去需求改變,我們希望得出總共有多少個不同的country,country相同的數據隨便返回其中一個就行,代碼如下所示:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國", City = "北京", Name = "小米" },new Phone { Country = "中國",City = "北京",Name = "華為"},new Phone { Country = "中國",City = "北京",Name = "聯想"},new Phone { Country = "中國",City = "臺北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國",City = "加州",Name = "蘋果"},new Phone { Country = "美國",City = "華盛頓",Name = "三星"}};var Lists2 = PhoneLists.Distinct<Phone>(new ListComparer<Phone>((x,y) => x.Country.Equals(y.Country)));foreach (var list in Lists){Console.WriteLine(list.Country + "-" + list.City + "-" + list.Name);}Console.Read();}我們對country字段進行去重,得到的結果如下圖所示:
再接下去,需求又變,我們要篩選出有多少不同的國家和城市,這意味著要對country和city兩個字段進行去重,代碼如下:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國", City = "北京", Name = "小米" },new Phone { Country = "中國",City = "北京",Name = "華為"},new Phone { Country = "中國",City = "北京",Name = "聯想"},new Phone { Country = "中國",City = "臺北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國",City = "加州",Name = "蘋果"},new Phone { Country = "美國",City = "華盛頓",Name = "三星"}};var Lists = PhoneLists.Distinct<Phone>(new ListComparer<Phone>((x, y) => x.Country.Equals(y.Country) && x.City.Equals(y.City)));foreach (var list in Lists){Console.WriteLine(list.Country + "-" + list.City + "-" + list.Name);}Console.Read();}執行結果如下圖所示:
可以看到,已經達到了多字段的去重復效果,即便遇到需要去重復多個字段也可以實現,以上為個人拙見。
總結
以上是生活随笔為你收集整理的C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: task2 EDA数据分析
- 下一篇: 自动图片轮播php源码,js实现自动图片