亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

linqdistinct不夠用了!

2019-11-14 14:04:07
字體:
來源:轉載
供稿:網友

問題引出:在實際中遇到一個問題,要進行集合去重,集合內存儲的是引用類型,需要根據id進行去重。這個時候linq 的distinct 就不夠用了,對于引用類型,它直接比較地址。測試數據如下:

    class Person    {        public int ID { get; set; }        public string Name { get; set; }    }    List<Person> list = new List<Person>()    {         new Person(){ID=1,Name="name1"},         new Person(){ID=1,Name="name1"},         new Person(){ID=2,Name="name2"},         new Person(){ID=3,Name="name3"}                    }; 

 

我們需要根據Person 的 ID 進行去重。當然使用linq Distinct 不滿足,還是有辦法實現的,通過GroupBy先分一下組,再取第一個數據即可。例如:

list.GroupBy(x => x.ID).Select(x => x.FirstOrDefault()).ToList()

通常通過GroupBy去實現也是可以的,畢竟在內存操作還是很快的。但這里我們用別的方式去實現,并且找到最好的實現方式。

 

一、通過IEqualityComparer接口

IEnumerable<T> 的擴展方法 Distinct 定義如下:

public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source);public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);

可以看到,Distinct方法有一個參數為 IEqualityComparer<T> 的重載。該接口的定義如下:

// 類型參數 T: 要比較的對象的類型。public interface IEqualityComparer<T>{    bool Equals(T x, T y);    int GetHashCode(T obj);}

通過實現這個接口我們就可以實現自己的比較器,定義自己的比較規則了。

這里有一個問題,IEqualityComparer<T> 的 T 是要比較的對象的類型,在這里就是 Person,那這里如何去獲得 Person 的屬性 id呢?或者說,對于任何類型,我如何知道要比較的是哪個屬性?答案就是:委托。通過委托,要比較什么屬性由外部指定。這也是linq 擴展方法的設計,參數都是委托類型的,也就是規則由外部定義,內部只負責調用。ok,我們看最后實現的代碼:

    //通過繼承EqualityComparer類也是一樣的。    class CustomerEqualityComparer<T,V> : IEqualityComparer<T>    {        PRivate IEqualityComparer<V> comparer;        private Func<T, V> selector;        public CustomerEqualityComparer(Func<T, V> selector)            :this(selector,EqualityComparer<V>.Default)        {                    }        public CustomerEqualityComparer(Func<T, V> selector, IEqualityComparer<V> comparer)        {            this.comparer = comparer;            this.selector = selector;        }        public bool Equals(T x, T y)        {            return this.comparer.Equals(this.selector(x), this.selector(y));        }        public int GetHashCode(T obj)        {            return this.comparer.GetHashCode(this.selector(obj));        }    }

 

(補充1)之前沒有把擴展方法貼出來,而且看到有朋友提到比較字符串忽略大小寫的問題(其實上面有兩個構造函數就可以解決這個問題)。這里擴展方法可以寫為:

    static class EnumerableExtention    {        public static IEnumerable<TSource> Distinct<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> selector)        {            return source.Distinct(new CustomerEqualityComparer<TSource,TKey>(selector));        }        //4.0以上最后一個參數可以寫成默認參數 EqualityComparer<T>.Default,兩個擴展Distinct可以合并為一個。        public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)        {            return source.Distinct(new CustomerEqualityComparer<TSource, TKey>(selector,comparer));        }    }

例如,要根據Person的Name忽略大小寫比較,就可以寫成:

list.Distinct(x => x.Name,StringComparer.CurrentCultureIgnoreCase).ToList(); //StringComparer實現了IEqualityComaparer<string> 接口

 

二、通過哈希表。第一種做法的缺點是不僅要定義新的擴展方法,還要定義一個新類。能不能只有一個擴展方法就搞定?可以,通過Dictionary就可以搞定(有HashSet就用HashSet)。實現方式如下:

        public static IEnumerable<TSource> Distinct<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> selector)        {                        Dictionary<TKey, TSource> dic = new Dictionary<TKey, TSource>();            foreach (var s in source)            {                TKey key = selector(s);                if (!dic.ContainsKey(key))                    dic.Add(key, s);            }            return dic.Select(x => x.Value);        }

 

三、重寫object方法。能不能連擴展方法也不要了?可以。我們知道 object 是所有類型的基類,其中有兩個虛方法,Equals、GetHashCode,默認情況下,.net 就是通過這兩個方法進行對象間的比較的,那么linq 無參的Distinct 是不是也是根據這兩個方法來進行判斷的?我們在Person里 override 這兩個方法,并實現自己的比較規則。打上斷點調試,發現在執行Distinct時,是會進入到這兩個方法的。代碼如下:

class Person{    public int ID { get; set; }    public string Name { get; set; }    public override bool Equals(object obj)    {        Person p = obj as Person;        return this.ID.Equals(p.ID);    }    public override int GetHashCode()    {        return this.ID.GetHashCode();    }}

在我的需求里,是根據id去重的,所以第三種方式提供了最優雅的實現。如果是其它情況,用前面的方法更通用。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产老师黑色丝袜高跟鞋| 久久偷看各类女兵18女厕嘘嘘| 中文字幕自拍vr一区二区三区| 国产欧美一区二区三区四区| 亚洲国产古装精品网站| 国产免费一区二区三区在线观看| 欧美丰满片xxx777| www.久久色.com| 91在线视频一区| 成人免费看黄网站| 日韩精品欧美国产精品忘忧草| 欧美日韩电影在线观看| 亚洲美女性视频| 亚洲人成人99网站| 国产精品亚发布| 国产精品情侣自拍| 亚洲欧美制服中文字幕| 精品伊人久久97| 91九色视频在线| 亚洲精品国产免费| 亚洲区一区二区| 久久噜噜噜精品国产亚洲综合| 国产欧美在线播放| 欧美怡春院一区二区三区| 精品久久久久久| 亚洲sss综合天堂久久| 欧美成人合集magnet| 亚洲综合大片69999| 国语对白做受69| 国产精品久久久久久久午夜| 青青在线视频一区二区三区| 粉嫩老牛aⅴ一区二区三区| 国产视频丨精品|在线观看| 国产99久久精品一区二区永久免费| 成人乱色短篇合集| 欧美激情在线观看| 国产精品一区二区电影| 97在线看福利| 国产精品美女999| 一本大道香蕉久在线播放29| 国a精品视频大全| 久久躁狠狠躁夜夜爽| 日韩电影第一页| 成人国产精品一区| 久久乐国产精品| 日韩精品有码在线观看| 亚洲一区二区三区sesese| 日韩性xxxx爱| 久青草国产97香蕉在线视频| 国产精品18久久久久久首页狼| 亚洲欧美国内爽妇网| 日本一区二区三区四区视频| 亚洲偷熟乱区亚洲香蕉av| 亚洲成人激情在线观看| 国产精品色婷婷视频| 国产精品美女免费| 中文字幕视频在线免费欧美日韩综合在线看| 欧美日韩国产二区| 久久五月天综合| 在线视频日本亚洲性| 亚洲伊人成综合成人网| 国产欧美精品在线| 成人午夜激情免费视频| 欧美精品在线观看91| 日本aⅴ大伊香蕉精品视频| 成人福利视频网| 91精品中文在线| 精品毛片三在线观看| 欧美极品第一页| 日韩av在线导航| 成人午夜一级二级三级| 视频一区视频二区国产精品| 26uuu国产精品视频| 午夜剧场成人观在线视频免费观看| 国产一区二区三区视频免费| 日韩免费观看高清| 亚洲精品国产电影| 国产精品2018| 精品久久久久久久久久ntr影视| 久久久久久亚洲精品中文字幕| 国产91精品视频在线观看| 97视频在线观看网址| 揄拍成人国产精品视频| 久久久中文字幕| 久久综合久久88| 亚洲成人免费在线视频| 免费av一区二区| 91九色国产视频| 日韩中文字幕在线免费观看| 亚洲第一页自拍| 亚洲2020天天堂在线观看| 亚洲热线99精品视频| 欧美做爰性生交视频| 国产成人短视频| 国产精品综合久久久| 欧美精品www在线观看| 久久久久久国产精品久久| 成人性生交大片免费看小说| 日韩动漫免费观看电视剧高清| 国产一区二区三区视频在线观看| 欧美日韩免费在线观看| 成人h猎奇视频网站| 中文字幕欧美亚洲| 国产精品啪视频| 国产日本欧美一区二区三区| 日韩美女视频中文字幕| 成人做爽爽免费视频| 欧美日韩视频在线| 亚洲免费影视第一页| 国产精品成人观看视频国产奇米| 欧美一级淫片videoshd| 国自在线精品视频| 91精品免费看| 国产成人亚洲综合青青| 成人在线精品视频| 亚洲影视中文字幕| 久久国产精品首页| 国产精品一区二区在线| 欧美激情一级二级| 国产精品成人v| 国产欧美精品一区二区三区-老狼| 夜夜嗨av色综合久久久综合网| 久久夜色精品国产欧美乱| 国产成人久久久精品一区| 精品久久久av| 欧美高跟鞋交xxxxhd| 国产剧情日韩欧美| 欧美日韩亚洲视频一区| 日韩国产精品亚洲а∨天堂免| 亚洲精品国产品国语在线| 亚洲iv一区二区三区| 国产美女91呻吟求| 久久久久久高潮国产精品视| 永久免费毛片在线播放不卡| 清纯唯美日韩制服另类| 国产精品老牛影院在线观看| 亚洲电影免费观看高清完整版| 久久亚洲精品视频| 久久久亚洲影院| 中文字幕精品视频| 精品久久久国产精品999| 黑人极品videos精品欧美裸| 国产v综合v亚洲欧美久久| 久久69精品久久久久久国产越南| 91精品久久久久| 成人在线免费观看视视频| 久久99国产精品自在自在app| 国产精品精品久久久久久| 亚洲成人a**站| 国产成人精品免高潮费视频| 91啪国产在线| 成人黄色av网| 精品无人区乱码1区2区3区在线| 欧美日韩亚洲系列| 正在播放亚洲1区| 欧美日韩加勒比精品一区| 欧美国产日本高清在线| 日韩av电影免费观看高清| 亚洲精品日韩激情在线电影| 欧美亚洲国产日韩2020| 亚洲精选一区二区| 精品国产欧美一区二区五十路| 亚洲欧洲国产伦综合| 欧美国产一区二区三区|