当前位置: 首页 > news >正文

C# Distinct方法的使用笔记

引自:http://blog.csdn.net/shaopengfei/article/details/36426763 

从C# 3.0开始提供了Distinct方法,这对于集合的使用有了更为丰富的方法,经过在网上搜索相应的资源,发现有关这方面的写的好的文章还是不少的。而且为了扩展Linq的使用不方便的地方,有一些办法非常有效。由于本人工作中的需要,有一些功能暂时没有用到那么深入,现在只把最简单的一些功能分享出来,整理出来。

  1. 简单一维集合的使用:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. List<int> ages = new List<int> { 21, 46, 46, 55, 17, 21, 55, 55 };  
    2. List<string> names = new List<string> { "wang", "li", "zhang", "li", "wang", "chen", "he", "wang" };  
    3.   
    4. IEnumerable<int> distinctAges = ages.Distinct();  
    5. Console.WriteLine("Distinct ages:");  
    6. foreach (int age in distinctAges)  
    7. {  
    8.      Console.WriteLine(age);  
    9. }  
    10.   
    11. var distinctNames = names.Distinct();  
    12. Console.WriteLine("\nDistinct names:");  
    13. foreach (string name in distinctNames)  
    14. {  
    15.      Console.WriteLine(name);  
    16. }  

     

    • 在这段代码中,是最简单的Distinct()方法的使用。使用了集合接口IEnumerable,以及隐式类型var,至于这两种用法有什么区别,没有研究出来。
    • 但是如果象下面这样的代码,是错误的!

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. List<int> disAge = ages.Distinct();  

     

    • 正确的方法应该是:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. List<int> ages = new List<int> { 21, 46, 46, 55, 17, 21, 55, 55 };  
    2.   
    3. List<int> disAge = ages.Distinct().ToList();  
    4. foreach (int a in disAge)  
    5.      Console.WriteLine(a);  

     

    • 也就是说Distinct()方法的返回集合类型是一个接口,不是具体的集合,所以需要用一个ToList()。
  2. 自定义类的使用:

    • 首先我们看MSDN上给出的例子,先定义一个产品类:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. public class Product : IEquatable<Product>  
    2. {  
    3.     public string Name { get; set; }  
    4.     public int Code { get; set; }  
    5.   
    6.     public bool Equals(Product other)  
    7.     {  
    8.   
    9.         //Check whether the compared object is null.  
    10.         if (Object.ReferenceEquals(other, null)) return false;  
    11.   
    12.         //Check whether the compared object references the same data.  
    13.         if (Object.ReferenceEquals(this, other)) return true;  
    14.   
    15.         //Check whether the products' properties are equal.  
    16.         return Code.Equals(other.Code) && Name.Equals(other.Name);  
    17.     }  
    18.   
    19.     // If Equals() returns true for a pair of objects   
    20.     // then GetHashCode() must return the same value for these objects.  
    21.   
    22.     public override int GetHashCode()  
    23.     {  
    24.   
    25.         //Get hash code for the Name field if it is not null.  
    26.         int hashProductName = Name == null ? 0 : Name.GetHashCode();  
    27.   
    28.         //Get hash code for the Code field.  
    29.         int hashProductCode = Code.GetHashCode();  
    30.   
    31.         //Calculate the hash code for the product.  
    32.         return hashProductName ^ hashProductCode;  
    33.     }  
    34. }  

     

    • 在主函数里,是这样用的:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. static void Main(string[] args)  
    2. {  
    3.     Product[] products =   
    4.     {  
    5.         new Product { Name = "apple", Code = 9 },   
    6.         new Product { Name = "orange", Code = 4 },   
    7.         new Product { Name = "apple", Code = 9 },  
    8.         new Product { Name = "lemon", Code = 12 }  
    9.     };  
    10.   
    11.     //Exclude duplicates.  
    12.     IEnumerable<Product> noduplicates =  
    13.         products.Distinct();  
    14.   
    15.     foreach (var product in noduplicates)  
    16.         Console.WriteLine(product.Name + " " + product.Code);  
    17. }  

     

    • 这样的输出是:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. /* 
    2.     This code produces the following output: 
    3.     apple 9  
    4.     orange 4 
    5.     lemon 12 
    6. */  

     

    • 但是现在的问题是,如果我们把主函数里改成这样:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. static void Main(string[] args)  
    2. {  
    3.     Product[] products =   
    4.     {  
    5.         new Product { Name = "Smallapple", Code = 9 },   
    6.         new Product { Name = "orange", Code = 4 },   
    7.         new Product { Name = "Bigapple", Code = 9 },  
    8.         new Product { Name = "lemon", Code = 12 }  
    9.     };  
    10.   
    11.     //Exclude duplicates.  
    12.     IEnumerable<Product> noduplicates =  
    13.         products.Distinct();  
    14.   
    15.     foreach (var product in noduplicates)  
    16.         Console.WriteLine(product.Name + " " + product.Code);  
    17. }  

     

    • 这样的输出是:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. /* 
    2.     This code produces the following output: 
    3.     Smallapple 9  
    4.     orange 4 
    5.     Bigapple 9 
    6.     lemon 12 
    7. */  

     

    • 我们的问题是,如果想按Code来索引,想找出Code唯一的这些成员,那么这里就需要重新定义一个对Code比较的类,或者再扩展成泛型类,但是这样非常繁琐。
  3. 博客鹤冲天的改进办法(以下均转自这个博客)

    • 首先,创建一个通用比较的类,实现IEqualityComparer<T>接口:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. public class CommonEqualityComparer<T, V> : IEqualityComparer<T>  
    2. {  
    3.     private Func<T, V> keySelector;  
    4.   
    5.     public CommonEqualityComparer(Func<T, V> keySelector)  
    6.     {  
    7.         this.keySelector = keySelector;  
    8.     }  
    9.   
    10.     public bool Equals(T x, T y)  
    11.     {  
    12.         return EqualityComparer<V>.Default.Equals(keySelector(x), keySelector(y));  
    13.     }  
    14.   
    15.     public int GetHashCode(T obj)  
    16.     {  
    17.         return EqualityComparer<V>.Default.GetHashCode(keySelector(obj));  
    18.     }  
    19. }  

     

    • 借助上面这个类,Distinct扩展方法就可以这样写:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. public static class DistinctExtensions  
    2. {  
    3.     public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)  
    4.     {  
    5.         return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));  
    6.     }  
    7. }  

     

    • 下面的使用就很简单了:

     

    [csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
     
    1. Product[] products =   
    2. {  
    3.     new Product { Name = "Smallapple", Code = 9 },   
    4.     new Product { Name = "orange", Code = 4 },   
    5.     new Product { Name = "Bigapple", Code = 9 },  
    6.     new Product { Name = "lemon", Code = 12 }  
    7. };  
    8.   
    9. var p1 = products.Distinct(p => p.Code);  
    10. foreach (Product pro in p1)  
    11.     Console.WriteLine(pro.Name + "," + pro.Code);  
    12. var p2 = products.Distinct(p => p.Name);  
    13. foreach (Product pro in p2)  
    14.     Console.WriteLine(pro.Name + "," + pro.Code);  

     

    • 可以看到,加上Linq表达式,可以方便的对自定义类的任意字段进行Distinct的处理。

转载于:https://www.cnblogs.com/biye/p/4018963.html

相关文章:

  • Linux远程桌面
  • Java Se : Java NIO(服务端)与BIO(客户端)通信
  • 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究...
  • SQL Server 2014 官方培训课件
  • 使用SSL证书保障网络游戏信息安全
  • vs2010 正式版官方下载地址
  • Python用subprocess的Popen来调用系统命令
  • gc overhead limit exceeded eclipse错误解决方式
  • 【错排问题】【HDU2048】神、上帝以及老天爷
  • 使用 CJSON 在C语言中进行 JSON 的创建和解析的实例讲解
  • MYSQL 数据表备份
  • JavaScript判断是否是手机mobile登录
  • Android性能优化之一:ViewStub
  • 通过js控制html页面不能右键,复制等
  • 如果ie6跳转
  • 【刷算法】从上往下打印二叉树
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Docker 笔记(2):Dockerfile
  • HTML中设置input等文本框为不可操作
  • input实现文字超出省略号功能
  • JavaScript类型识别
  • JS实现简单的MVC模式开发小游戏
  • Linux gpio口使用方法
  • React组件设计模式(一)
  • Ruby 2.x 源代码分析:扩展 概述
  • VUE es6技巧写法(持续更新中~~~)
  • - 概述 - 《设计模式(极简c++版)》
  • 基于webpack 的 vue 多页架构
  • 那些被忽略的 JavaScript 数组方法细节
  • 通过npm或yarn自动生成vue组件
  •  一套莫尔斯电报听写、翻译系统
  • 移动端 h5开发相关内容总结(三)
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​第20课 在Android Native开发中加入新的C++类
  • !!Dom4j 学习笔记
  • (02)vite环境变量配置
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (四)汇编语言——简单程序
  • (未解决)macOS matplotlib 中文是方框
  • (五)关系数据库标准语言SQL
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET中winform传递参数至Url并获得返回值或文件
  • .Net中的集合
  • @EventListener注解使用说明
  • @RequestBody与@ModelAttribute
  • [.NET]桃源网络硬盘 v7.4
  • []C/C++读取串口接收到的数据程序
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子
  • [C puzzle book] types
  • [C# 基础知识系列]专题十六:Linq介绍