c# 扩展方法奇思妙用基础篇八:Distinct 扩展(转载)
转载地址:http://www.cnblogs.com/ldp615/archive/2011/08/01/distinct-entension.html
刚看了篇文章 《Linq的Distinct太不给力了》,文中给出了一个解决办法,略显复杂。
试想如果能写成下面的样子,是不是更简单优雅:
1 2 |
var p1 = products.Distinct(p => p.ID); var p2 = products.Distinct(p => p.Name); |
使用一个简单的 lambda 作为参数,也符合 Linq 一贯的风格。
可通过扩展方法实现:
Distinct 扩展方法
首先,创建一个通用比较的类,实现 IEqualityComparer<T> 接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Linq;public class CommonEqualityComparer<T, V> : IEqualityComparer<T> {private Func<T, V> keySelector;public CommonEqualityComparer(Func<T, V> keySelector){this.keySelector = keySelector;}public bool Equals(T x, T y){return EqualityComparer<V>.Default.Equals(keySelector(x), keySelector(y));}public int GetHashCode(T obj){return EqualityComparer<V>.Default.GetHashCode(keySelector(obj));} } |
第 17 行,用到了 EqualityComparer<T> 类,本文最后有简要说明。
借助上面这个类,Distinct 扩展方法就很好写了:
1 2 3 4 5 6 7 |
public static class DistinctExtensions {public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector){return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));} } |
呵呵,简单吧!
Distinct 使用示例
根据 ID :
1 2 3 4 5 6 7 |
var data1 = new Person[] {new Person{ ID = 1, Name = "鹤冲天"},new Person{ ID = 1, Name = "ldp"} }; var ps1 = data1.Distinct(p => p.ID).ToArray(); |
根据 Name:
1 2 3 4 5 7 |
var data2 = new Person[] {new Person{ ID = 1, Name = "鹤冲天"},new Person{ ID = 2, Name = "鹤冲天"} }; var ps2 = data2.Distinct(p => p.Name).ToArray(); |
看了回复后,我做了些改进,推荐使用下面的方式:
改进
回复中有朋友提到“不区分大小写地排除重复的字符串”,也不难实现,只需要把上面的代码改进下就 OK:
CommonEqualityComparer<T, V> 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Linq;public class CommonEqualityComparer<T, V> : IEqualityComparer<T> {private Func<T, V> keySelector;private IEqualityComparer<V> comparer;public CommonEqualityComparer(Func<T, V> keySelector, IEqualityComparer<V> comparer){this.keySelector = keySelector;this.comparer = comparer;}public CommonEqualityComparer(Func<T, V> keySelector): this(keySelector, EqualityComparer<V>.Default){ }public bool Equals(T x, T y){return comparer.Equals(keySelector(x), keySelector(y));}public int GetHashCode(T obj){return comparer.GetHashCode(keySelector(obj));} } |
Distinct 扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 |
public static class DistinctExtensions {public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector){return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));}public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector, IEqualityComparer<V> comparer){return source.Distinct(new CommonEqualityComparer<T, V>(keySelector, comparer));} } |
借助可选参数,这两个扩展方法也可以合成一个:
1 2 3 4 5 |
public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector, IEqualityComparer<V> comparer = EqualityComparer<V>.Default) {return source.Distinct(new CommonEqualityComparer<T, V>(keySelector, comparer)); } |
(同样,CommonEqualityComparer<T, V>类的两个构造函数也可以合二为一)
使用示例:
1 2 3 4 5 6 7 |
var data3 = new Person[] {new Person{ ID = 1, Name = "LDP"},new Person{ ID = 2, Name = "ldp"} }; var ps3 = data3.Distinct(p => p.Name, StringComparer.CurrentCultureIgnoreCase).ToArray(); |
EqualityComparer<T> 类 简要说明
EqualityComparer<T>为 IEqualityComparer<T> 泛型接口的实现提供基类,它在 .net 4 中有五个重要的子类,见下图:
这五个子类分别用不同类型数据的相等性比较,从类名我们可以略知一二。
这五个子类都是内部类(internal),不能直接访问,EqualityComparer<T> 类提供一个简单的属性 Default。EqualityComparer<T> 会根据传入的 T 的类型,加载不同的子类,并会予以缓存提高性能。
基础篇: | 中文处理、string 常用扩展、byte 常用扩展、Random 扩展、Dictionary<TKey, TValue> 扩展、WhereIf 扩展、IsBetween 通用扩展、WhereIf 扩展、Distinct 扩展 |
高级篇: | 改进 Scottgu 的 "In" 扩展、Aggregate扩展其改进、Enumerable.Cast<T>应用、对扩展进行分组管理、ToString(string format) 扩展、WinForm 控件选择器、树”通用遍历器、Type类扩展 |
变态篇: | 由Fibonacci数列引出“委托扩展”及“递推递归委托”、封装 if/else、swith/case及while、switch/case 组扩展、string 的翻身革命 |
性能篇: | 扩展方法性能初测 |
MVC篇: | 巧用扩展方法优先级,美化所有页面TextBoxFor文本框 |
-------------------
转载于:https://www.cnblogs.com/yxlblogs/p/3737164.html
c# 扩展方法奇思妙用基础篇八:Distinct 扩展(转载)相关推荐
- c#扩展方法奇思妙用性能篇一:扩展方法性能初测
最近写了几篇<c#扩展方法奇思妙用>的文章,一直只是讨论如何扩展.如何使用的问题,几乎没有涉及效率方面. 而大家的回复好多都在问效率如何.性能怎样,也引起了我对效率的关注,今天将初步测试的 ...
- c#扩展方法奇思妙用高级篇八:Type类扩展
Type 类提供了大量的属性和方法,但在一些基础性开发工作中,Type类功能还有些欠缺,尤其上在处理泛型类型时,如可空类型和泛型集合类型.下面的类就针对这些地方进行扩展. 1 public ...
- c#扩展方法奇思妙用高级篇七:“树”通用遍历器
我的上一篇随笔<c#扩展方法奇思妙用高级篇六:WinForm 控件选择器>中给出了一个WinForm的选择器,其实质就是一个"树"的遍历器,但这个遍历局限于WinFor ...
- c#扩展方法奇思妙用高级篇四:对扩展进行分组管理
从系列文章开篇到现在,已经实现的很多扩展了,但过多的扩展会给我们带来很多麻烦,试看下图: 面对这么多"泛滥"的扩展,很多人都会感到很别扭,的确有种"喧宾夺主"的 ...
- c# 扩展方法奇思妙用变态篇四:string 的翻身革命
string是各种编程语言中最基础的数据类型,长期以来受尽其它类的压迫,经常被肢解(Substring.Split).蹂躏(Join)... 而现在string要"翻身闹革命"了, ...
- c#扩展方法奇思妙用变态篇四:string 的翻身革命
string是各种编程语言中最基础的数据类型,长期以来受尽其它类的压迫,经常被肢解(Substring.Split).蹂躏(Join)... 而现在string要"翻身闹革命"了, ...
- c# 扩展方法奇思妙用高级篇一:改进 Scottgu 的 In 扩展
先看下ScottGu对In的扩展: 调用示例1: 调用示例2: 原文地址:New "Orcas" Language Feature: Extension Methods 很多介绍扩 ...
- c# 扩展方法奇思妙用变态篇一:由 Fibonacci 数列引出 “委托扩展” 及 “递推递归委托”...
先回顾一个数列的概念:按一定次序排列的一列 数 称为数列...(请参见百度百科:数列) 几个简单的数列: 1, 1, 1, 1, 1, 1, 1... //数 ...
- C#扩展方法奇思妙用高级篇一:改进 Scottgu 的 In 扩展
先看下ScottGu对In的扩展: 调用示例1: 调用示例2: 原文地址:New "Orcas" Language Feature: Extension Methods 很多介绍扩 ...
最新文章
- 1行Python代码制作动态二维码
- python使用fpdf生成数据报告pdf文件
- 物联网白皮书【2018】重磅发布|今年的物联网产业交出了一张怎样的答卷
- 将现有Git存储库推送到SVN
- 在Nature都点赞的大会上,马斯克被「脑机接口之父」炮轰了:他说的话,我一个字都不认同...
- 解决Windows环境下Git Bash 不能输入中文的问题
- 卸载VS2005不完全出现的安装问题
- Java中static的用法,初始化块
- 如何使用bat批处理命令打开WSL
- 苹果开发者中心如何上传构建版本
- postgreSQL 获取当前连接的IP
- Linux 修改hosts文件
- raid5硬盘插到计算机读取,【哭着写下这篇文章】win2008软raid5变成2个磁盘组的数据恢复...
- Fabric学习笔记(六) - chaincode开发模式
- python opencv 入门 绘图函数 (3)
- Unity开发3 坐标系及工具、快捷键操作
- 恭喜!第十届“吴文俊人工智能科学技术奖”揭晓!华章多位作译者获奖
- 路由器端口转发数量限制_路由器可以同时处理的设备数量是否有限制?
- 软件快捷方式测试用例,用TestDirector生成的测试用例
- 码讯化工人员定位系统/支持无线WiFi|UWB定位
热门文章
- Lua源码分析 - 基础篇 - Lua源码的结构和架构图(01)
- 非常值得一看—九种滤波算法C语言实现
- java 远程shell脚本_java通过ssh连接服务器执行shell命令详解及实例
- mysql的内连接查询
- c++ primer 5th p289页练习题自己的解答程序
- 让C++对象只能分配到堆/栈和静态区上并判断分配位置
- 概率论-4.2中心极限定理(待补充)
- 对于原生代码使用Java线程的优缺点
- 华为手机如何升级鸿蒙系统_华为官方正式公告!鸿蒙手机系统下周发布:普通花粉何时能升级?...
- Apache Hadoop 简单配置及实践