C# 您所在的位置:网站首页 如何进行复杂排序 C#

C#

2023-09-02 08:15| 来源: 网络整理| 查看: 265

本文通过示例介绍了C#中典型容器List.Sort()的自定义排序方法,进而引出了C#中自定义排序的核心接口及方法

项目地址:自定义Sort方法 - SouthBegonia's Github

List.Sort() 为我们提供了4种自定义排序方法,通过对这些方法改进我们可以轻松做到对多参数、多规则的复杂排序:

List.Sort(); List.Sort(IComparer Comparer); List.Sort(int index, int count, IComparer Comparer); List.Sort(Comparison comparison); 项目背景

存在People类,包含Name、Age属性,在客户端中创建List保存多个实例,对List根据Name和Age参数进行排序:

class People { public People(string name, int age) { Name = name; Age = age; } public string Name { get; set; } public int Age { get; set; } } // 客户端 class Client { static void Main(string[] args) { List peopleList = new List(); peopleList.Add(new People("张三", 22)); peopleList.Add(new People("张三", 24)); peopleList.Add(new People("李四", 18)); peopleList.Add(new People("王五", 16)); peopleList.Add(new People("王五", 30)); } } List.Sort()

该方法为系统默认的方法,单一参数时会默认进行升序排序。但遇到多参数(Name、Age)排序时,我们需要对该默认方法进行修改。

方法:People类继承IComparable,实现CompareTo()方法 IComparable:定义由值类型或类实现的通用比较方法,旨在创建特定于类型的比较方法以对实例进行排序。 原理:自行实现的CompareTo()方法会在list.Sort()内部进行元素两两比较,最终实现排序 class People : IComparable { public People(string name, int age) { Name = name;Age = age; } public string Name { get; set; } public int Age { get; set; } // list.Sort()时会根据该CompareTo()进行自定义比较 public int CompareTo(People other) { if (this.Name != other.Name) { return this.Name.CompareTo(other.Name); } else if (this.Age != other.Age) { return this.Age.CompareTo(other.Age); } else return 0; } } // 客户端 peopleList.Sort(); // OUTPUT: // 李四 18 // 王五 16 // 王五 30 // 张三 22 // 张三 24 List.Sort(IComparer Comparer)

区别于上述继承IComparable的方法,该方法不可在People内继承实现IComparer接口,而是需要新建比较方法类进行接口实现

方法:新建PeopleComparer类、继承IComparer接口、实现Compare()方法 原理:list.Sort()将PeopleComparer类的实例作为参数,在内部使用Compare()方法进行两两比较,最终实现排序(注:上述方法为CompareTo(),此处为Compare()方法) // 自定义比较方法类 class PeopleComparer : IComparer { // 区别于CompareTo()单参数,此处为双参数 public int Compare(People x, People y) { if (x.Name != y.Name) { return x.Name.CompareTo(y.Name); } else if (x.Age != y.Age) { return x.Age.CompareTo(y.Age); } else return 0; } } // 客户端 // 传入参数为自定义比较类的实例 peopleList.Sort(new PeopleComparer()); // OUTPUT: // 李四 18 // 王五 16 // 王五 30 // 张三 22 // 张三 24

同理,List.Sort(int index, int count, IComparer Comparer) 方法的参数:待排元素起始索引、待排元素个数、排序方法

List.Sort(Comparison comparison)

区别于上述继承接口的方法,此方法的参数为 泛型委托 Comparison

委托原型:public delegate int Comparison(T x, T y); 方法:依照委托的使用方法,首先创建委托实例MyComparison,并绑定到自定义的比较方法PeopleComparison()上,最终调用list.Sort()时 将委托实例传入 原理:list.Sort()根据传入的委托方法,进行两两元素比较最终实现排序 // 客户端 class Client { // 自定义比较方法 public static int PeopleComparison(People p1, People p2) { if (p1.Name != p2.Name) { return p1.Name.CompareTo(p2.Name); } else if (p1.Age != p2.Age) { return p1.Age.CompareTo(p2.Age); } else return 0; } static void Main(string[] args) { /* 创建list ... */ // 创建委托实例并绑定 Comparison MyComparison = PeopleComparison; // 传入该实例实现比较方法 peopleList.Sort(MyComparison); // OUTPUT: // 李四 18 // 王五 16 // 王五 30 // 张三 22 // 张三 24 } }

此外,既然Comparison是泛型委托,则完全可以用 Lambda表达式 进行描述:

// Lambda表达式实现Comparison委托 peopleList.Sort((p1, p2) => { if (p1.Name != p2.Name) { return p2.Name.CompareTo(p1.Name); } else if (p1.Age != p2.Age) { return p2.Age.CompareTo(p1.Age); } else return 0; }); // OUTPUT: // 张三 24 // 张三 22 // 王五 30 // 王五 16 // 李四 18 总结

虽然本文仅使用了List一种容器对Sort()方法进行阐述,但是不同容器的使用Sort()的方法大相径庭,因为核心的原理都是应用两种接口及泛型委托:

两种接口:IComparable 、 IComparer 泛型委托:Comparison 参考 IComparable接口 - Microsoft Comparison委托 - Microsoft IComparer接口 - Microsoft IComparable和IComparer接口和自定义比较器 - My_Pure


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有