问题描述:Person类有两个属性ID(int)、Name(string)属性。筛选序列中不重复的Person。

class Person
   2: {
int ID { get; set; }
string Name { get; set; }
   5: }

好吧,看样子得用Distinct方法。不过Distinct方法有两个重载。

static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source
   3: )
   4:  
static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source,
   7:     IEqualityComparer<TSource> comparer
   8: )

看样子已经够用了。不过如果我想只按ID唯一,或者按Name唯一呢?派生IEqualityComparer倒是可以解决。不过那也忒坑爹了。还是自己试着写一个扩展吧。

 

Distinct扩展

版本1

参考封装的Distinct的方法先写一个。声明一个List<TSource>,循环的时候比较,如果不同就加进去。

this IEnumerable<TSource> source, Func<TSource, TProperty> selector)
   2: {
);
);
new List<TSource>();
in source)
   7:     {
if (temp.Any(t => selector(t).Equals(selector(item))))
   9:         {
continue;
  11:         }
  12:         temp.Add(item);
  13:     }
return temp;
  15: }

测试一下,没什么问题。不过在函数里声明List<TSource>感觉怪怪的,想办法换种方式。

new List<Person>() 
   2: {
 },
 },
 },
 }
   7: };
   8:  
   9: var temp = list.Distinct(t => t.ID);

版本2

取指定属性的唯一序列,在循环的时候使用yield返回。

this IEnumerable<TSource> source, Func<TSource, TProperty> selector)
   2: {
);
);
   5:  
   6:     var pdis = source.Select(t => selector(t)).Distinct();
in pdis)
   8:     {
return source.First(t => selector(t).Equals(item));
  10:     }
  11: }

测试通过。

用Stopwatch分别测试两个函数循环不同次数的时间。对比一下,循环次数在10,000次以上时,版本2耗时大概是版本1的1/40,性能差距算是比较大。

 

后记

目前来说已经够用了,如果还有其他需求,再根据情况扩展吧。

   1: list.Distinct(t => t.ID);
new { t.ID, t.Name }); //根据ID及Name的值分别比较来取唯一,并非比较引用

相关文章: