linq中distinct扩展,快速创建IComparer<T> 的实例
1.功能描述:要实现这么一个功能:取出下载前10名的应用,且10个应用分别属于不同的类。
2.问题描述:因为采用NoSql存数,数据已经存在list实体中,所以打算采用linq中distinct的方法实现它,实体类结构为:
public class KBase
{
public int kId {get;set}
public string SName {get;set}
public int CId {get;set} //类别Id
.
.
.
};
list实现中有40条数据(存在CId重复记录),数据较多,省去不列举出来,实现如下:
var distinctApkBase = KBase.distinct();
结果出来没得到我想要的,重复cId的记录还是存在,后来才发现Distinct默认比较的是KBase对象的引用
接续使用Distinct方法的另一个重载:
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);该重载接收一个IEqualityComparer的参数。
假设要按Id来筛选,那么应该新建类CategoryIdComparer 内容如下:
public class CategoryIdComparer : IEqualityComparer<KBase>
{
public bool Equals(KBase x, KBase y)
{
if (x == null)
return y == null;
return x.CId == y.CId;
}
public int GetHashCode(KBase obj)
{
if (obj == null)
return 0;
return obj.CategoryId.GetHashCode();
}
}
使用的时候,只需要
var distinctKBase = KBase.Distinct(new CategoryIdComparer());结果是可以过滤重复的cId了,但按照这样的方式,如果我要按SName进行distinct的话,又要重新写一个类SNameComparer
3.解决办法:后面根据net 中 IEqualityComparer<T> 和 IComparer<T>整了一个类以实现快速创建IComparer<T> 的实例:
public static class ComparisonHelper<T>
{
public static IComparer<T> CreateComparer<V>(Func<T, V> keySelector)
{
return new CommonComparer<V>(keySelector);
}
public static IComparer<T> CreateComparer<V>(Func<T, V> keySelector, IComparer<V> comparer)
{
return new CommonComparer<V>(keySelector, comparer);
}
class CommonComparer<V> : IComparer<T>
{
private Func<T, V> keySelector;
private IComparer<V> comparer;
public CommonComparer(Func<T, V> keySelector, IComparer<V> comparer)
{
this.keySelector = keySelector;
this.comparer = comparer;
}
public CommonComparer(Func<T, V> keySelector)
: this(keySelector, Comparer<V>.Default) //Comparer<V> 类和它的 Default 属性是关键
{ }
public int Compare(T x, T y)
{
return comparer.Compare(keySelector(x), keySelector(y));
}
}
}
使用方法:
var comparer1 = Comparison<ApkBase>.CreateComparer(p => p.ApkId);
var comparer2 = Comparison<ApkBase>.CreateComparer(p => p.ApkSoftName);
var comparer3 = Comparison<ApkBase>.CreateComparer(p => p.CategoryId);
浙公网安备 33010602011771号