c#中,list.sort() 不仅为我们提供了默认的排序方法,还为我们提供了4种自定义排序的方法,通过默认排序方法,我们无需重写任何sort()方法的实现代码,就能对单参数类型的list数据进行单一规则的排序,如果通过对这些方法进行改进我们可以轻松做到对多参数、多规则的复杂排序。
c# 默认排序方法sort、reverse
排序sort,倒序reverse
//默认是元素第一个字母按升序 list.sort(); //将list里面元素顺序反转 list.reverse(); //从第二个元素开始,反转4个元素 //结果list里最后的顺序变成"ha", "jay", "lily", "tom", "hunter", "jim", "kuku", "locu" list.reverse(1,4);
c#自定义排序的4种方法
list<t>.sort(); list<t>.sort(icomparer<t> comparer); list<t>.sort(int index, int count, icomparer<t> comparer); list<t>.sort(comparison<t> 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<people> peoplelist = new list<people>(); 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)); } }
方法一、继承icomparable接口,实现compareto()方法
对people类继承icomparable接口,实现compareto()方法
该方法为系统默认的方法,单一参数时会默认进行升序排序。但遇到多参数(name、age)排序时,我们需要对该默认方法进行修改。
方法一:people类继承icomparable接口,实现compareto()方法
icomparable<t>:定义由值类型或类实现的通用比较方法,旨在创建特定于类型的比较方法以对实例进行排序。
原理:自行实现的compareto()方法会在list.sort()内部进行元素两两比较,最终实现排序
class people : icomparable<people> { 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
方法二:增加外部比较类,继承icomparer接口、实现compare()方法
增加people类的外部比较类,继承icomparer接口、实现compare()方法
区别于上述继承icomparable的方法,该方法不可在people内继承实现icomparer接口,而是需要新建比较方法类进行接口实现
方法二:新建peoplecomparer类、继承icomparer接口、实现compare()方法
原理:list.sort()将peoplecomparer类的实例作为参数,在内部使用compare()方法进行两两比较,最终实现排序(注:上述方法为compareto(),此处为compare()方法)
// 自定义比较方法类 class peoplecomparer : icomparer<people> { // 区别于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<t>.sort(int index, int count, icomparer<t> comparer) 方法的参数:待排元素起始索引、待排元素个数、排序方法
方法三、采用泛型委托 comparison<t>,绑定自定义的比较方法
区别于上述继承接口的方法,此方法的参数为 泛型委托 comparison<t>
委托原型:public delegate int comparison<in t>(t x, t y);
方法三:依照委托的使用方法,首先创建委托实例mycomparison,并绑定到自定义的比较方法peoplecomparison()上,最终调用list.sort()时 将委托实例传入
原理:list.sort()根据传入的委托方法,进行两两元素比较最终实现排序
// 客户端 class client { // 方法0 自定义比较方法 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 ... / // 方法0 创建委托实例并绑定 comparison<people> mycomparison = peoplecomparison; // 传入该实例实现比较方法 peoplelist.sort(mycomparison); // output: // 李四 18 // 王五 16 // 王五 30 // 张三 22 // 张三 24 } }
泛型委托用lambda表达式
此外,既然comparison<t>
是泛型委托,则完全可以用 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<t>一种容器对sort()方法进行阐述,但是不同容器的使用sort()的方法大相径庭,因为核心的原理都是应用两种接口及泛型委托:
两种接口:icomparable<t> 、 icomparer<t>
泛型委托:comparison<t>
参考
icomparable接口 - microsoft icomparable
comparison委托 - microsoft comparison
icomparer接口 - microsoft icomparer 接口 (system.collections) | microsoft docs
icomparable和icomparer接口和自定义比较器 - my_pure c# icomparable和icomparer接口和自定义比较器
附:一个完整的测试demo
using system; using system.collections.generic; using system.linq; using system.text; namespace listsort { class program { static void displayinfo<t>(list<t> list) { //输出list元素内容 foreach(var item in list) { system.console.write("{0} ",item.tostring()); } system.console.writeline(""); } // 方法3 自定义委托泛型比较方法 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<people> peoplelist = new list<people>(); 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)); system.console.writeline("排序前原始数据:"); displayinfo(peoplelist); system.console.writeline("------------------------------------"); system.console.writeline("方法1排序后数据:"); peoplelist.sort(); displayinfo(peoplelist); system.console.writeline("方法2排序后数据:"); displayinfo(peoplelist); // 方法1 使用icomparer<t>接口。 peoplelist.sort(new peoplecomparer()); // 方法2 除以上两种方法以外还可以使用另一种方法,在people类中实现icomparable<t> peoplelist.sort(); system.console.writeline("方法3排序后数据:"); displayinfo(peoplelist); // 方法3 创建泛型委托实例并绑定 comparison<people> mycomparison = peoplecomparison; // 传入该实例实现比较方法 peoplelist.sort(mycomparison); system.console.writeline("方法3排序后数据:"); displayinfo(peoplelist); // 方法3 使用comparison<t>委托,lambda写法 peoplelist.sort((left, right) => { //先按姓名排序,如果姓名相同再按年龄排序 int x = left.name.compareto(right.name); if(x==0) { if (left.age > right.age) x = 1; else if (left.age == right.age) x = 0; else x = -1; } return x; }); } } //方法一 public class people : icomparable<people> { public int age { get;set;} public string name { get;set;} public people(string name,int age) { this.name = name; this.age = age; } public override string tostring() { string result = ""; result = "["+this.name+","+ this.age.tostring()+"]"; return result; } public int compareto(people other) { int x = this.name.compareto(other.name); if(x==0) { if (this.age > other.age) x = 1; else if (this.age == other.age) x = 0; else x = -1; } return x; } } //方法二 public class peoplecomparer : icomparer<people> { public int compare(people left, people right) { int x = left.name.compareto(right.name); if(x==0) { if (left.age > right.age) x = 1; else if (left.age == right.age) x = 0; else x = -1; } return x; } } }
到此这篇关于c# list.sort排序(默认排序和自定义排序)的文章就介绍到这了,更多相关c# list.sort排序内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论