C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重
背景說明
在EF等ORM框架中需要以List實(shí)體類的方式對(duì)數(shù)據(jù)進(jìn)行大量操作,其中免不了對(duì)一些數(shù)據(jù)進(jìn)行去重復(fù),而C#中IEnumerable.Distinct()便提供了這一功能。只是對(duì)剛開始接觸的新人來說比價(jià)抽象難以接受,本文會(huì)對(duì)這一功能進(jìn)行簡(jiǎn)要說明,如果有更好的實(shí)現(xiàn)方式,也請(qǐng)大家暢所語(yǔ)言。
在寫本文時(shí),本人也在網(wǎng)上搜索了很多相關(guān)資料,其中有幾篇比較有參考價(jià)值,也是重點(diǎn),本文也是基于這幾篇文章提供的代碼進(jìn)行優(yōu)化和整理:
1、用泛型委托實(shí)現(xiàn)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
我們要做的是實(shí)現(xiàn)IEqualityComparer()接口,而且必須要用泛型,因?yàn)槲覀兿M@個(gè)功能是可以對(duì)所有實(shí)體類實(shí)現(xiàn)的。其中對(duì)哈希值的了解可以參考第三條鏈接,可以簡(jiǎn)單的概括為,哈希值反應(yīng)的是對(duì)象在內(nèi)存中的地址,只有地址相同的對(duì)象才能激活I(lǐng)EqualityComparer中的Equal()方法,Equal()可以根據(jù)自己的需求而實(shí)現(xiàn)。話不多說,代碼如下:
/// <summary>/// 用委托實(shí)現(xiàn)IEqualityComparer<T>接口/// </summary>/// <typeparam name="T">目標(biāo)類型</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>/// 獲取目標(biāo)對(duì)象的哈希值,只有返回相同的哈希值才能運(yùn)行Equals方法/// </summary>/// <param name="obj">獲取哈希值的目標(biāo)類型對(duì)象</param>/// <returns>返回哈希值</returns>public int GetHashCode(T obj){if (this.GetHashCodeFunc != null){return this.GetHashCodeFunc(obj);}else{return 0;}}}以上代碼中,默認(rèn)哈希值是相同的,我們開始看看使用效果,代碼如下:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國(guó)", City = "北京", Name = "小米" },new Phone { Country = "中國(guó)",City = "北京",Name = "華為"},new Phone { Country = "中國(guó)",City = "北京",Name = "聯(lián)想"},new Phone { Country = "中國(guó)",City = "臺(tái)北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國(guó)",City = "加州",Name = "蘋果"},new Phone { Country = "美國(guó)",City = "華盛頓",Name = "三星"}};var Lists = PhoneLists.Distinct<Phone>();foreach (var list in Lists){Console.WriteLine(list.Country + "-" + list.City + "-" + list.Name);}Console.Read();}在Distinct()方法沒有任何參數(shù)的情況下,運(yùn)行后如下圖所示:
我們可以看到,好像并沒有任何效果,但是其實(shí)是有效果的,因?yàn)槊總€(gè)Phone實(shí)體類對(duì)象在內(nèi)存中的地址是不一樣的,? ? ? ? ?Distinct()方法默認(rèn)篩選出所有內(nèi)存地址不一樣的實(shí)體類對(duì)象。
接下去需求改變,我們希望得出總共有多少個(gè)不同的country,country相同的數(shù)據(jù)隨便返回其中一個(gè)就行,代碼如下所示:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國(guó)", City = "北京", Name = "小米" },new Phone { Country = "中國(guó)",City = "北京",Name = "華為"},new Phone { Country = "中國(guó)",City = "北京",Name = "聯(lián)想"},new Phone { Country = "中國(guó)",City = "臺(tái)北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國(guó)",City = "加州",Name = "蘋果"},new Phone { Country = "美國(guó)",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();}我們對(duì)country字段進(jìn)行去重,得到的結(jié)果如下圖所示:
再接下去,需求又變,我們要篩選出有多少不同的國(guó)家和城市,這意味著要對(duì)country和city兩個(gè)字段進(jìn)行去重,代碼如下:
static void Main(string[] args){List<Phone> PhoneLists = new List<Phone>(){new Phone { Country = "中國(guó)", City = "北京", Name = "小米" },new Phone { Country = "中國(guó)",City = "北京",Name = "華為"},new Phone { Country = "中國(guó)",City = "北京",Name = "聯(lián)想"},new Phone { Country = "中國(guó)",City = "臺(tái)北",Name = "魅族"},new Phone { Country = "日本",City = "東京",Name = "索尼"},new Phone { Country = "日本",City = "大阪",Name = "夏普"},new Phone { Country = "美國(guó)",City = "加州",Name = "蘋果"},new Phone { Country = "美國(guó)",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();}執(zhí)行結(jié)果如下圖所示:
可以看到,已經(jīng)達(dá)到了多字段的去重復(fù)效果,即便遇到需要去重復(fù)多個(gè)字段也可以實(shí)現(xiàn),以上為個(gè)人拙見。
總結(jié)
以上是生活随笔為你收集整理的C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: task2 EDA数据分析
- 下一篇: C#中@符号的作用