C# 中distinct的使用
假设我们有一个类:Product
public class Product { public string Id { get; set; } public string Name { get; set; } }
Main函数如下:
static void Main() { List<Product> products = new List<Product>() { new Product(){ Id="1", Name="n1"}, new Product(){ Id="1", Name="n2"}, new Product(){ Id="2", Name="n1"}, new Product(){ Id="2", Name="n2"}, }; var distinctProduct = products.Distinct(); Console.ReadLine(); }
可以看到distinctProduct 的结果是:
因为Distinct 默认比较的是Product对象的引用,所以返回4条数据。
那么如果我们希望返回Id唯一的product,那么该如何做呢?
Distinct方法还有另一个重载:
//通过使用指定的 System.Collections.Generic.IEqualityComparer<T> 对值进行比较 //返回序列中的非重复元素。 public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source,
IEqualityComparer<TSource> comparer);
该重载接收一个IEqualityComparer的参数。
假设要按Id来筛选,那么应该新建类ProductIdComparer 内容如下:
public class ProductIdComparer : IEqualityComparer<Product> { public bool Equals(Product x, Product y) { if (x == null) return y == null; return x.Id == y.Id; } public int GetHashCode(Product obj) { if (obj == null) return 0; return obj.Id.GetHashCode(); } }
使用的时候,只需要
var distinctProduct = products.Distinct(new ProductIdComparer());
结果如下:
现在假设我们要 按照 Name来筛选重复呢?
很明显,需要再添加一个类ProductNameComparer.
那能不能使用泛型类呢??
新建类PropertyComparer<T> 继承IEqualityComparer<T> 内容如下:
public class PropertyComparer<T> : IEqualityComparer<T> { private PropertyInfo _PropertyInfo; /// <summary> /// 通过propertyName 获取PropertyInfo对象
/// </summary> /// <param name="propertyName"></param> public PropertyComparer(string propertyName) { _PropertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public); if (_PropertyInfo == null) { throw new ArgumentException(string.Format("{0} is not a property of type {1}.", propertyName, typeof(T))); } } #region IEqualityComparer<T> Members public bool Equals(T x, T y) { object xValue = _PropertyInfo.GetValue(x, null); object yValue = _PropertyInfo.GetValue(y, null); if (xValue == null) return yValue == null; return xValue.Equals(yValue); } public int GetHashCode(T obj) { object propertyValue = _PropertyInfo.GetValue(obj, null); if (propertyValue == null) return 0; else return propertyValue.GetHashCode(); } #endregion }
主要是重写的Equals 和GetHashCode 使用了属性的值比较。
使用的时候,只需要:
//var distinctProduct = products.Distinct(new PropertyComparer<Product>("Id")); var distinctProduct = products.Distinct(new PropertyComparer<Product>("Name"));
结果如下:
为什么微软不提供PropertyEquality<T> 这个类呢?
按照上面的逻辑,这个类应该没有很复杂啊,细心的同学可以发现PropertyEquality 大量的使用了反射。每次获取属性的值的时候,都在调用
_PropertyInfo.GetValue(x, null);
可想而知,如果要筛选的记录非常多的话,那么性能无疑会受到影响。
为了提升性能,可以使用表达式树将反射调用改为委托调用,
具体代码如下:
public class FastPropertyComparer<T> : IEqualityComparer<T> { private Func<T, Object> getPropertyValueFunc = null; /// <summary> /// 通过propertyName 获取PropertyInfo对象 /// </summary> /// <param name="propertyName"></param> public FastPropertyComparer(string propertyName) { PropertyInfo _PropertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public); if (_PropertyInfo == null) { throw new ArgumentException(string.Format("{0} is not a property of type {1}.", propertyName, typeof(T))); } ParameterExpression expPara = Expression.Parameter(typeof(T), "obj"); MemberExpression me = Expression.Property(expPara, _PropertyInfo); getPropertyValueFunc = Expression.Lambda<Func<T, object>>(me, expPara).Compile(); } #region IEqualityComparer<T> Members public bool Equals(T x, T y) { object xValue = getPropertyValueFunc(x); object yValue = getPropertyValueFunc(y); if (xValue == null) return yValue == null; return xValue.Equals(yValue); } public int GetHashCode(T obj) { object propertyValue = getPropertyValueFunc(obj); if (propertyValue == null) return 0; else return propertyValue.GetHashCode(); } #endregion }
可以看到现在获取值只需要getPropertyValueFunc(obj) 就可以了。
使用的时候:
var distinctProduct = products.Distinct(new FastPropertyComparer<Product>("Id")).ToList();
C# 中distinct的使用的更多相关文章
- SQL中distinct的用法
SQL中distinct的用法 1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...
- Thinkphp 中 distinct 的用法
TP中distinct()的用处主要是去除重复的值 在Thinkphp手册中也详细说明了(链接:http://document.thinkphp.cn/manual_3_2.html#distinct ...
- MySQL中distinct和group by性能比较[转]
MySQL中distinct和group by性能比较[转] 之前看了网上的一些测试,感觉不是很准确,今天亲自测试了一番.得出了结论(仅在个人计算机上测试,可能不全面,仅供参考) 测试过程: 准备一张 ...
- SQL中distinct的用法和left join查询的含义
SQL中distinct的用法 1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...
- Thinkphp中distinct的用法
Thinkphp中distincat的用法 TP中distinct()的用处主要是去除重复的值 在Thinkphp手册中也详细说明了(链接:http://document.thinkphp.cn/ma ...
- hive中select中DISTINCT的技巧和使用
hive中select中DISTINCT的技巧和使用 单表的唯一查询用:distinct 多表的唯一查询用:group by 在使用MySQL时,有时需要查询出某个字段不重复的记录,虽然mysql提供 ...
- mysql中distinct的用法
本事例实验用表task,结构如下 MySQL> desc task; +-------------+------------+------+-----+-------------------+- ...
- 扩展lamda表达中distinct按照字段去除重复
首先,我们定义一个Student类来测试. public class Student { public int ID { get; set; } public string Name { get; s ...
- SQL中distinct的用法(转自博主:Rain Man)
在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值.关键词 distinct用于返回唯一不同的值. 表A: 示例1 select distinct nam ...
随机推荐
- sh脚本学习之: sh脚本 、sed、awk
sh脚本 sh命令的批处理文件,支持更复杂的逻辑. Shell中的变量 参数 $0 当前脚本路径 $1....$n 脚本执行对应的第n个参数 条件判断 文件判断 test [op] path e存在 ...
- Systemd入门教程:命令篇
导读 传统的Linux系统启动过程主要由著名的init进程(也被称为SysV init启动系统)来处理,而基于init的启动系统被认为有效率不足的问题,systemd是Linux系统机器的另一种启动方 ...
- unity3d进行脚本资源打包加载
原地址:http://www.cnblogs.com/hisiqi/p/3204752.html 本文记录如何通过unity3d进行脚本资源打包加载 1.创建TestDll.cs文件 public c ...
- IOS项目删除Git
默认创建工程会在MAC上面创建Git版本管理, 但是呢, 我现在想上传到svn服务器进行管理, 但是已经有个git 好像上传不了 只有把Git删了才能继续. 连问带查, 终于找到解决方案 把 .git ...
- cocos2d回忆
凭借自己的回忆想想看自己都学到了那些知识,这是小学的时候当初中老师的外公给我说的,现在想想,CCDirector,CCNode,CCScene,CCSprite这几个类,然后是坐标,锚点,CCNode ...
- OpenCV入门(二)
这次主要学习了下滤波,就当复习了图像处理的知识了:http://blog.csdn.net/poem_qianmo/article/details/22745559 代码实现比较简单,但关于通过滚动条 ...
- HDOJ 1596
9899828 2013-12-27 16:42:37 Accepted 1596 3312MS 6668K 711 B C++ 泽泽 floyed暴力 #include<cstdio> ...
- ubuntu14.04 中国源
deb http://cn.archive.ubuntu.com/ubuntu/ trusty main restricted universe multiversedeb http://cn.arc ...
- Hydra---Linux下的暴力美学
引自:http://www.cnblogs.com/mchina/archive/2013/01/01/2840815.html 安装:http://www.91ri.org/2867.html yu ...
- Android Studio中的Module,Facet
详细内容请参看 http://www.jetbrains.com/idea/webhelp/facet.html 以及 http://www.jetbrains.com/idea/webhelp/an ...