Distinct删除重复数据时 自定义的方法比较【转】
最近项目中在用Linq Distinct想要将重复的资料去除时,发现它跟Any之类的方法有点不太一样,不能很直觉的在呼叫时直接带入重复数据判断的处理逻辑,所以当我们要用某个成员属性做重复数据的判断时,就必需绕一下路,这边稍微将处理的方法做个整理并记录一下。
首先为了方便接下去说明,我们必须先来准备后面会用到的数据类别,这边一样用笔者最常用来示范的Person类别,内含两个成员属性ID与Name。
01.public struct Person02.{03.#region Property04./// <summary>05./// Gets or sets the ID.06./// </summary>07./// <value>The ID.</value>08.public string ID { get; set; }09. 10./// <summary>11./// Gets or sets the name.12./// </summary>13./// <value>The name.</value>14.public string Name { get; set; }15.#endregion16. 17. 18.#region Public Method19./// <summary>20./// Returns a <see cref="System.String"/> that represents this instance.21./// </summary>22./// <returns>23./// A <see cref="System.String"/> that represents this instance.24./// </returns>25.public override string ToString()26.{27.return Name;28.}29.#endregion接着准备要用来测试的资料,这边准备了十一个Person对象,前十个对象的名称都是Larry,第十一个对象的名称为LastLarry。期望后面可以透过Distinct将重复的Larry过滤掉。
...
1.var datas = new List<Person>();2.int idx = 0;3.for (idx = 0; idx < 10; ++idx)4.{5.datas.Add(new Person() {ID = idx.ToString(), Name = "Larry" });6.}7.datas.Add(new Person() { ID = idx.ToString(), Name = "LastLarry" });8....若是我们想直接用内建的Distinct函式来过滤数据。
...
01.var distinctDatas = datas.Distinct();02.ShowDatas(distinctDatas);03....04.private static void ShowDatas<T>(IEnumerable<T> datas)05.{06.foreach (var data in datas)07.{08.Console.WriteLine(data.ToString());09.}10.}可以看到运行起来并不如我们所预期的,过滤出来的数据跟没过滤一样。

为了解决这个问题,我们必须要做个可依照Person.Name去做比较的Compare类别,该Compare类别必须实做IEqualityCompare.Equals与IEqualityCompare.GetHashCode方法,并在呼叫Distinct过滤时将该Compare对象带入。
01.distinctDatas = datas.Distinct(new PersonCompare());02.ShowDatas(distinctDatas);03....04.class PersonCompare : IEqualityComparer<Person>05.{06.#region IEqualityComparer<Person> Members07. 08.public bool Equals(Person x, Person y)09.{10.return x.Name.Equals(y.Name);11.}12. 13.public int GetHashCode(Person obj)14.{15.return obj.Name.GetHashCode();16.}17. 18.#endregion19.}运行起来就会是我们所期望的样子。

www.it165.net
但是这样做代表我们每次碰到新的类别就必须要实现对应的Compare类别,用起来十分的不便。因此有人就提出用泛型加上反射的方式做一个共享的Compare类别。
01.public class PropertyComparer<T> : IEqualityComparer<T>02.{03.private PropertyInfo _PropertyInfo;04. 05./// <summary>06./// Creates a new instance of PropertyComparer.07./// </summary>08./// <param name="propertyName">The name of the property on type T09./// to perform the comparison on.</param>10.public PropertyComparer(string propertyName)11.{12.//store a reference to the property info object for use during the comparison13._PropertyInfo = typeof(T).GetProperty(propertyName,14.BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);15.if (_PropertyInfo == null)16.{17.throw new ArgumentException(string.Format("{0} is not a property of type {1}.", propertyName, typeof(T)));18.}19.}20. 21.#region IEqualityComparer<T> Members22. 23.public bool Equals(T x, T y)24.{25.//get the current value of the comparison property of x and of y26.object xValue = _PropertyInfo.GetValue(x, null);27.object yValue = _PropertyInfo.GetValue(y, null);28. 29.//if the xValue is null then we consider them equal if and only if yValue is null30.if (xValue == null)31.return yValue == null;32. 33.//use the default comparer for whatever type the comparison property is.34.return xValue.Equals(yValue);35.}36. 37.public int GetHashCode(T obj)38.{39.//get the value of the comparison property out of obj40.object propertyValue = _PropertyInfo.GetValue(obj, null);41. 42.if (propertyValue == null)43.return 0;44. 45.else46.return propertyValue.GetHashCode();47.}48. 49.#endregion50.}使用时只要带入泛型的型态与成原属性的名称,就可以产生出需要的Compare对象。
1.distinctDatas = datas.Distinct(new PropertyComparer<Person>("Name"));2.ShowDatas(distinctDatas);这样的作法是减少了许多额外的负担,但是感觉还是少了一条路,用起来也还是必须要建立Compare对象,而且反射也存在着效能的问题,如果每个元素都透过这个Compare去做判断,感觉处理上也不是很漂亮。所以有人也意识到了这个问题,用扩充方法提供了一条我们比较熟悉的路,可以直接将Lambda带入以决定元素要怎样过滤。
01.public static class EnumerableExtender02.{03.public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)04.{05.HashSet<TKey> seenKeys = new HashSet<TKey>();06.foreach (TSource element in source)07.{08.var elementValue = keySelector(element);09.if (seenKeys.Add(elementValue))10.{11.yield return element;12.}13.}14.}15.}使用上会好写许多。
1.distinctDatas = datas.Distinct(person => person.Name);2.ShowDatas(distinctDatas);若是不想加入额外的类别,我们也可以透过Group方式来达到类似的效果。
1.distinctDatas = from data in datas2.group data by data.Name into g3.select g.First();4.ShowDatas(distinctDatas);Distinct删除重复数据时 自定义的方法比较【转】的更多相关文章
- Linq使用Distinct删除重复数据时如何指定所要依据的成员属性zz
最近项目中在用Linq Distinct想要将重复的资料去除时,发现它跟Any之类的方法有点不太一样,不能很直觉的在呼叫时直接带入重复数据判断的处理逻辑,所以当我们要用某个成员属性做重复数据的判断时, ...
- Oracle 删除重复数据的几种方法
去重 第一种:distinct create table tmp_t3 as select distinct * from t3; drop table t3; alter table tmp_t2 ...
- Excel删除重复数据及用公式筛选重复项并标记颜色突出显示
当表格记录比较多时,常常会有重复数据,而重复记录往往只希望保存一条,因此需要把多余的删除:在 Excel 中,删除重复数据有两种方法,一种是用"删除重复数据"删除,另一种是用&qu ...
- orcl数据库查询重复数据及删除重复数据方法
工作中,发现数据库表中有许多重复的数据,而这个时候老板需要统计表中有多少条数据时(不包含重复数据),只想说一句MMP,库中好几十万数据,肿么办,无奈只能自己在网上找语句,最终成功解救,下面是我一个实验 ...
- MySQL中删除重复数据的简单方法,mysql删除重复数据
MYSQL里有五百万数据,但大多是重复的,真实的就180万,于是想怎样把这些重复的数据搞出来,在网上找了一圈,好多是用NOT IN这样的代码,这样效率很低,自己琢磨组合了一下,找到一个高效的处理方式, ...
- oracle中查找和删除重复记录的几种方法总结
平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452 :不能创建唯一索引,发现重复记录. 下面总结一下几种查找和删除重复记录的方法(以表CZ为例): 表CZ的结 ...
- T-SQL技术收集——删除重复数据
原文:T-SQL技术收集--删除重复数据 在工作和面试中,经常出现如何查询或者删除重复数据的问题,如果有主键,那还好办一点,如果没有主键,那就有点麻烦. 当一个表上没有辅助键时,如果使用SSMS界面来 ...
- 【MySQL】测试MySQL表中安全删除重复数据只保留一条的相关方法
第二篇文章测试说明 开发测试中,难免会存在一些重复行数据,因此常常会造成一些测试异常. 下面简单测试mysql表删除重复数据行的相关操作. 主要通过一下三个大标题来测试说明: 02.尝试删除dept_ ...
- 取两个DataTable的交集,删除重复数据
/// <summary> /// 取两个DataTable的交集,删除重复数据 /// </summary> /// <param name="sourceD ...
随机推荐
- LayoutInflater(四)
如果说要按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.那么下面我们就来依次学习一下,每种方式分别是如何自定义View的. 一.自绘控件 自绘控件的意思就 ...
- thinkphp几个表的数据合并,并用数组分页
控制器: //金币扣除 public function jbkc(){ $map['UG_dataType']= 'xtkc'; $list1 = M ( 'userget' )->where ...
- EventBus代替Intent将复杂对象传递给下一个即将启动的Activity
我觉得EventBus确实非常好,把我们从序列化中解脱出来,即使不序列化也能在界面间传递数据,但是有个前提,那是两个界面都已经存在并且注册了EventBus.而即将启动的下一个Activity就非常尴 ...
- css随记02布局
布局 二栏布局 利用absolute, margin .container { position: relative; } nav { position: absolute; left: 0px; w ...
- linux(centos6)搭建ftp服务器
前提 ssh服务已经开启,关闭防火墙,主机和虚拟机能ping通 查看ssh和防火墙的状态 service sshd status service iptables status 开启ssh服务 ser ...
- 解决eclipse报PermGen space内存溢出异常的问题
异常问题如下所示: 1.点击Eclipse->Window->Preferences,如下所示: 2.点击Server->Runtime Environments,选择Apache ...
- JavaScrip实现3D旋转动态效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 矩阵快速幂 ZOJ 3497 Mistwald
题目传送门 题意:看似给了一个迷宫,每个点能传送到4个地方,问在P时间能否到达终点 分析:其实是一个有向图,可以用邻接矩阵存图,连乘P次看是否能从1到n*m,和floyd的传递背包思想一样 #incl ...
- three.js入门2
新建一个html文件 <!DOCTYPE html> <html> <head> <title></title> <style> ...
- HIT2715 Matrix3(最小费用最大流)
题目大概说有一个n×n的矩阵,每个格子都有权值和高度,在这个矩阵中进行最多k次旅行,每次旅行能从当前格子走到相邻且高度更小的格子,走到格子边界就能出去完成这次旅行.每走到一个格子就累加格子的权值然后把 ...