使用Linq过滤重复对象的时候,我们使用Distinct。

但是Distinct对int long等值类型才有效果,对于对象我们需要自己写个对象。

以下利用泛型封装了两个类:

CommonComparer<T>

public class CommonComparer<T> : IEqualityComparer<T>
{
Func<T, string> GetStrigPropertyValueFunc;
Func<T, int> GetInt32PropertyValueFunc;
Func<T, long> GetInt64PropertyValueFunc; public CommonComparer(string propertyName)
{
var tType = typeof(T);
PropertyInfo propertyInfo = tType.GetProperty(propertyName); ParameterExpression pExpress = Expression.Parameter(tType);
MemberExpression bodyExpress = Expression.Property(pExpress, propertyInfo); switch (propertyInfo.PropertyType.Name)
{
case "Int32":
GetInt32PropertyValueFunc = Expression.Lambda<Func<T, int>>(bodyExpress, pExpress).Compile();
break;
case "Int64":
GetInt64PropertyValueFunc = Expression.Lambda<Func<T, long>>(bodyExpress, pExpress).Compile();
break;
case "String":
GetStrigPropertyValueFunc = Expression.Lambda<Func<T, string>>(bodyExpress, pExpress).Compile();
break;
default: throw new NotSupportedException("对比器只支持int32、int64、String");
}
} public bool Equals(T x, T y)
{
if (GetStrigPropertyValueFunc != null)
{
var xValue = GetStrigPropertyValueFunc(x);
var yValue = GetStrigPropertyValueFunc(y); if (xValue == null) return yValue == null;
return xValue.Equals(yValue);
}
else if (GetInt32PropertyValueFunc != null)
{
var xValue = GetInt32PropertyValueFunc(x);
var yValue = GetInt32PropertyValueFunc(y); if (xValue == null) return yValue == null;
return xValue.Equals(yValue);
}
else if (GetInt64PropertyValueFunc != null)
{
var xValue = GetInt64PropertyValueFunc(x);
var yValue = GetInt64PropertyValueFunc(y); if (xValue == null) return yValue == null;
return xValue.Equals(yValue);
} throw new NotSupportedException("没找到支持的委托类型");
} public int GetHashCode(T obj)
{
if (GetStrigPropertyValueFunc != null)
{
var value = GetStrigPropertyValueFunc(obj);
if (obj == null) return 0; return value.GetHashCode();
}
else if (GetInt32PropertyValueFunc != null)
{
var value = GetInt32PropertyValueFunc(obj);
if (obj == null) return 0; return value.GetHashCode();
}
else if (GetInt64PropertyValueFunc != null)
{
var value = GetInt64PropertyValueFunc(obj);
if (obj == null) return 0; return value.GetHashCode();
} return 0;
}
}

  

ReflectCommonComparer<T>

 public class ReflectCommonComparer<T> : IEqualityComparer<T>
{
string PropertyName; public ReflectCommonComparer(string propertyName)
{
PropertyName = propertyName;
} object GetPropertyValue(T x)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(PropertyName);
return propertyInfo.GetValue(x);
} public bool Equals(T x, T y)
{
var xValue = GetPropertyValue(x);
var yValue = GetPropertyValue(y); if (xValue == null) return yValue == null;
return xValue.Equals(yValue);
} public int GetHashCode(T obj)
{
var value = GetPropertyValue(obj);
if (obj == null) return 0; return value.GetHashCode();
}
}

  

CommonComparer利用的是表达式树来实现的,ReflectCommonComparer是利用反射来实现的。网络上说利用的是表达式树来实现比反射更快。

我做了简单的时间测试,以下是截图:

1000次循环对比,反射更快呀

十万次对比,也是反射的比较快呀。

有可能是我写的表达式树有问题。 有空再去试试。

---

我把去重的数据量变多了之后的对比:

十万次,表达式树更快了。

我的结论是,去重的数据量多的话就用表达式树,少的话就用反射。大概超过80就需要用表达式树了。

因此以上还可以进一步分装。

public static class LinqExtension
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, string propertyName)
{
if (source.Count() > 80)
return source.Distinct(new CommonComparer<T>(propertyName));
else
return source.Distinct(new ReflectCommonComparer<T>(propertyName));
}
}

  使用

var newList = list.Distinct("id").ToList(); // id是要用来判断去重的唯一值

  

为Distinct准备的通用对比器的更多相关文章

  1. python 通用装饰器,带有参数的装饰器,

    # 使用装饰器对有返回值的函数进行装饰# def func(functionName): # print('---func-1----') # def func_in(): # print(" ...

  2. 通用采集器Modbus协议应用

    1.  功能码 通用采集器一般包含DI,DO,AI相关接口,对此类接口主要应用功能码01~06. 3类接口具体对应关系如下: 继电器定义,功能码01/05(01:读线圈,05写线圈) 序号       ...

  3. Atitit..状态机与词法分析  通用分词器 分词引擎的设计与实现 attilax总结

    Atitit..状态机与词法分析  通用分词器 分词引擎的设计与实现 attilax总结 1. 状态机 理论参考1 2. 词法分析理论1 3. 词法分析实例2 4. ---code fsm 状态机通用 ...

  4. 新闻网页通用抽取器GNEv0.04版更新,支持提取正文图片与源代码

    GeneralNewsExtractor以下简称GNE是一个新闻网页通用抽取器,能够在不指定任何抽取规则的情况下,把新闻网站的正文提取出来. 我们来看一下它的基本使用方法. 安装 GNE 使用 pip ...

  5. MySQL 里面的Where 和Having和Count 和distinct和Group By对比

    mysql> select accid as uid,date(datetime) AS datetime from game.logLogin GROUP BY accid HAVING da ...

  6. Scut:通用配置管理器

    1. 配置节 ConfigSection private List<ConfigNode> _configNodes; public class ConfigNode { public C ...

  7. 面向切面编程AOP,一些通用装饰器

    1.一些装饰器,可以减少重复编写.比较常用的. 用的时候函数上面加上装饰器就可以.这是一些装饰器,加在函数或者方法上,减少了很多重复代码. 除此之外工作中也用一些mixin类大幅减少代码. impor ...

  8. python 通用 修饰器

    import functools def log(option): def dec(func): def swapper(*arg, **karg): functools.update_wrapper ...

  9. 【C#】基础之数组排序,对象大小比较(对比器)

    C#基础之数组排序,对象大小比较 原文链接:[OutOfMemory.CN] 从个小例子开始: 1 2 3 int[] intArray = new int[]{2,3,6,1,4,5}; Array ...

随机推荐

  1. session的使用

    一.什么是session? Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 Web 页之间跳转时, ...

  2. apache和nginx原理上的不同之处

    今天群里提到面试时问到apache和nginx原理有什么不同,一时还真没想起,想到的只是他们的优缺点,便搜索了下.记录学习下.顺便记录下优缺点吧. 原理不同之处: 为什么Nginx的性能要比Apach ...

  3. String类的实现(4)写时拷贝浅析

    由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间.这种方法就是写时拷贝.这也是一种 ...

  4. 使用EPPlus读写xlsx文件

    朋友有个需求,想对N张excel表做过滤和合并的处理,拜托我写个小程序.因为用户的背景是非专业用户,因此最好的选择是写个GUI程序,再加上读写excel的需求,所以我的首选就是C#的WinForm了. ...

  5. Letter Combinations of a Phone Number:深度优先和广度优先两种解法

    Letter Combinations of a Phone Number Given a digit string, return all possible letter combinations ...

  6. [Linux] PHP程序员玩转Linux系列-Linux和Windows安装nginx

    1.PHP程序员玩转Linux系列-怎么安装使用CentOS 2.PHP程序员玩转Linux系列-lnmp环境的搭建 3.PHP程序员玩转Linux系列-搭建FTP代码开发环境 4.PHP程序员玩转L ...

  7. jQ层级选择器

    <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...

  8. JAVA加密算法系列-AesEBC

    package ***; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java. ...

  9. 整合第二次(SSM第一次)------------>spring+struts2+mybatis

    今天我们来讲解一下SSM整合,感觉整合这个比上一篇整合更费时,原因在于自己不太熟悉MyBatis了,下午的时候恶补了一下,看了一下相关的文档和PDF电子书,知识真的是你不用就会忘记的,以后还是不能懈怠 ...

  10. 一个可能让你记忆力飙升的软件 —— 这是一道填空(keng)题

    本文题目的两个含义: 1.填上次挖的坑,将优化后的软件分享给需要的网友(下载链接附在文末): 还没有看过的网友可以先看看这篇文章: 一个可能让你记忆力飙升的软件 2.这个软件的本质其实就是生成各种填空 ...