• C#中的IComparable 和 IComparer 接口,实现列表中的对象比较和排序


      借豆瓣某博主的话先对这两个接口进行一个解释:

      IComparable在要比较的对象的类中实现,可以比较该对象和另一个对象
      

      IComparer在一个单独的类中实现,可以比较任意两个对象。

      如果已经支持 IComparer 的类型 (如 字符串 或 整数) 的数组可以对该数组进行排序而无需提供 IComparer 任何显式引用。在这种情况下该数组的元素强制转换为您 IComparer(Comparer.Default) 的默认实现。但是,如果您想要提供您自定义的对象进行排序或比较功能,则必须实现这些接口的一项或两项。


    IComparable
      IComparable 的作用是提供了一种比较两个对象的特定类型的方法。这是必需的如果您想要为对象提供任何排序功能。视为 IComparable 提供您的对象的默认排序次序。例如对于如果您有一个您的类型的对象的数组,并在该数组上调用 Sort 方法 IComparable 在排序过程中提供对象的比较。实现 IComparable 界面时, 必须实现 CompareTo 方法,如下所示:

    1 int IComparable.CompareTo(object obj)
    2 {
    3      car c=(car)obj;
    4      return String.Compare(this.make,c.make);
    5 }


      方法中的比较是不同的要比较的值数据类型 depending on。因为选择了比较属性是字符串,此示例中使用 String.Compare。


    IComparer
      IComparer 的角色是提供附加的比较机制。例如对于您可能需要提供几个字段或属性,在类中的顺序升序和降序在同一字段或两者。
      使用 IComparer 是一个包含两个步骤的过程:
       1)声明一个类实现 IComparer,然后实现比较方法:
      

     1 private class sortYearAscendingHelper : IComparer
     2 {
     3    int IComparer.Compare(object a, object b)
     4    {
     5       car c1=(car)a;
     6       car c2=(car)b;
     7       if (c1.year > c2.year)
     8          return 1;
     9       if (c1.year < c2.year)
    10          return -1;
    11       else
    12          return 0;
    13    }
    14 }


      2)声明一个返回 IComparer 对象的实例的方法:

    1 public static IComparer sortYearAscending()
    2 { 
    3    return (IComparer) new sortYearAscendingHelper();
    4 }

      在此的示例为第二个参数时,调用重载的 Array.Sort 方法接受 IComparer 使用对象。IComparer 的使用并不限于数组。它将被接受作为许多不同的集合和控件类中的参数。

      

      而在List<T>中已经有了排序的方法了.Sort(参数),参数为比较器,共有四种重载。

      

    NameDescription
    Public methodSort() Sorts the elements in the entireList<T> using the default comparer.
    Public methodSort(Comparison<T>) Sorts the elements in the entireList<T> using the specifiedSystem.Comparison<T>.
    Public methodSort(IComparer<T>) Sorts the elements in the entireList<T> using the specified comparer.
    Public methodSort(Int32, Int32, IComparer<T>) Sorts the elements in a range of elements in List<T> using the specified comparer.

      第一种就是默认排序,只对常见的类型比如int,float,double,string等可以自身比较的类型。默认升序排序。、

      第二种为Comparison<T>,此处是指定比较的模式,只需要写一个简单的比较函数即可,比如:

     1 private static int CompareDinosByLength(string x, string y)//这里的参数一般是要比较的List内的元素
     2     {
     3         if (x == null)
     4         {
     5             if (y == null)
     6                 return 0;
     7             else
     8                 return -1;
     9         }
    10         else
    11         {
    12             if (y == null)
    13                 return 1;
    14             else
    15             {
    16                 int retval = x.Length.CompareTo(y.Length);
    17                 if (retval != 0)
    18                     return retval;
    19                 else
    20                     return x.CompareTo(y);
    21             }
    22         }
    23     }
    24 
    25 int static Main()
    26 {
    27         List<string> dinosaurs = new List<string>();
    28         dinosaurs.Add("Pachycephalosaurus");
    29         dinosaurs.Add("Amargasaurus");
    30         dinosaurs.Add("");
    31         dinosaurs.Add(null);
    32         dinosaurs.Add("Mamenchisaurus");
    33         dinosaurs.Add("Deinonychus");
    34         Display(dinosaurs);
    35 
    36         Console.WriteLine("
    Sort with generic Comparison<string> delegate:");
    37         dinosaurs.Sort(CompareDinosByLength);
    38 }

      第三种相对复杂一点,需要新设置一个比较器,并且实现接口,实现其中的函数,比如:

     1 public class DinoComparer: IComparer<string>
     2 {
     3     public int Compare(string x, string y)
     4     {
     5         if (x == null)
     6         {
     7             if (y == null)
     8                 return 0;
     9             else
    10                 return -1;
    11         }
    12         else
    13         {
    14             if (y == null)
    15                 return 1;
    16             else
    17             {
    18                 int retval = x.Length.CompareTo(y.Length);
    19 
    20                 if (retval != 0)
    21                     return retval;
    22                 else
    23                     return x.CompareTo(y);
    24             }
    25         }
    26     }
    27 }
    28 
    29 public class Example
    30 {
    31     public static void Main()
    32     {
    33         List<string> dinosaurs = new List<string>();
    34         dinosaurs.Add("Pachycephalosaurus");
    35         dinosaurs.Add("Amargasaurus");
    36         dinosaurs.Add("Mamenchisaurus");
    37         dinosaurs.Add("Deinonychus");
    38 
    39         DinoComparer dc = new DinoComparer();
    40         dinosaurs.Sort(dc);
    41     }

      第四种则是在第三中的基础之上添加指定的索引内的排序。

      那么在写好的比较器上怎么实现逆转排序呢?就是如果原先是正序,那么想要反序如何?看排序函数的返回值都是int类型,所以想要反序只需要在调用时前面加  - (负)即可。一般正序排序的返回值:-1代表前小后大,0代表相等,1代表前大后小,排序效果为从小到大。

      调用时是使用函数名调用,所以必须写两个函数了。使用Linq的排序可以使用前加符号的方式:http://www.tuicool.com/articles/aqU3eee

  • 相关阅读:
    x+=y与x=x+y有什么区别?
    Linux下带宽流量工具iftop实践
    使用pinyin4j实现汉字转拼音
    Spring整合Velocity模版引擎
    Json工具类库之Gson实战笔记
    腾讯移动分析 签名代码示例
    Docker搭建Portainer可视化界面
    maven 打包 spring boot 生成docker 镜像
    Mysql 为什么要选择 B+Tree
    idea 添加 注释 配置
  • 原文地址:https://www.cnblogs.com/yushuo1990/p/4759661.html
Copyright © 2020-2023  润新知