C#?List.Sort排序(默認排序和自定義排序)
C#中,List.Sort() 不僅為我們提供了默認的排序方法,還為我們提供了4種自定義排序的方法,通過默認排序方法,我們無需重寫任何Sort()方法的實現(xiàn)代碼,就能對單參數(shù)類型的List數(shù)據(jù)進行單一規(guī)則的排序,如果通過對這些方法進行改進我們可以輕松做到對多參數(shù)、多規(guī)則的復(fù)雜排序。
C# 默認排序方法Sort、Reverse
排序Sort,倒序Reverse
//默認是元素第一個字母按升序 list.Sort(); //將List里面元素順序反轉(zhuǎn) list.Reverse(); //從第二個元素開始,反轉(zhuǎn)4個元素 //結(jié)果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);
實現(xiàn)目標(biāo)
假設(shè)存在一個People類,包含Name、Age屬性,在客戶端中創(chuàng)建List保存多個實例,希望對List中的內(nèi)容根據(jù)Name和Age參數(shù)進行排序,排序規(guī)則為,先按姓名升序排序,如果姓名相同再按年齡的升序排序:
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接口,實現(xiàn)CompareTo()方法
對People類繼承IComparable接口,實現(xiàn)CompareTo()方法
該方法為系統(tǒng)默認的方法,單一參數(shù)時會默認進行升序排序。但遇到多參數(shù)(Name、Age)排序時,我們需要對該默認方法進行修改。
方法一:People類繼承IComparable接口,實現(xiàn)CompareTo()方法
IComparable<T>:定義由值類型或類實現(xiàn)的通用比較方法,旨在創(chuàng)建特定于類型的比較方法以對實例進行排序。
原理:自行實現(xiàn)的CompareTo()方法會在list.Sort()內(nèi)部進行元素兩兩比較,最終實現(xiàn)排序
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()時會根據(jù)該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接口、實現(xiàn)Compare()方法
增加People類的外部比較類,繼承IComparer接口、實現(xiàn)Compare()方法
區(qū)別于上述繼承IComparable的方法,該方法不可在People內(nèi)繼承實現(xiàn)IComparer接口,而是需要新建比較方法類進行接口實現(xiàn)
方法二:新建PeopleComparer類、繼承IComparer接口、實現(xiàn)Compare()方法
原理:list.Sort()將PeopleComparer類的實例作為參數(shù),在內(nèi)部使用Compare()方法進行兩兩比較,最終實現(xiàn)排序(注:上述方法為CompareTo(),此處為Compare()方法)
// 自定義比較方法類
class PeopleComparer : IComparer<People>
{
// 區(qū)別于CompareTo()單參數(shù),此處為雙參數(shù)
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;
}
}
// 客戶端
// 傳入?yún)?shù)為自定義比較類的實例
peopleList.Sort(new PeopleComparer());
// OUTPUT:
// 李四 18
// 王五 16
// 王五 30
// 張三 22
// 張三 24同理,List<T>.Sort(int index, int count, IComparer<T> Comparer) 方法的參數(shù):待排元素起始索引、待排元素個數(shù)、排序方法
方法三、采用泛型委托 Comparison<T>,綁定自定義的比較方法
區(qū)別于上述繼承接口的方法,此方法的參數(shù)為 泛型委托 Comparison<T>
委托原型:public delegate int Comparison<in T>(T x, T y);
方法三:依照委托的使用方法,首先創(chuàng)建委托實例MyComparison,并綁定到自定義的比較方法PeopleComparison()上,最終調(diào)用list.Sort()時 將委托實例傳入
原理:list.Sort()根據(jù)傳入的委托方法,進行兩兩元素比較最終實現(xiàn)排序
// 客戶端
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)
{
/ 創(chuàng)建list ... /
// 方法0 創(chuàng)建委托實例并綁定
Comparison<People> MyComparison = PeopleComparison;
// 傳入該實例實現(xiàn)比較方法
peopleList.Sort(MyComparison);
// OUTPUT:
// 李四 18
// 王五 16
// 王五 30
// 張三 22
// 張三 24
}
}泛型委托用Lambda表達式
此外,既然Comparison<T>是泛型委托,則完全可以用 Lambda表達式 進行描述:
// Lambda表達式實現(xiàn)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總結(jié)
雖然本文僅使用了List<T>一種容器對Sort()方法進行闡述,但是不同容器的使用Sort()的方法大相徑庭,因為核心的原理都是應(yīng)用兩種接口及泛型委托:
兩種接口: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元素內(nèi)容
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("排序前原始數(shù)據(jù):");
DisplayInfo(peopleList);
System.Console.WriteLine("------------------------------------");
System.Console.WriteLine("方法1排序后數(shù)據(jù):");
peopleList.Sort();
DisplayInfo(peopleList);
System.Console.WriteLine("方法2排序后數(shù)據(jù):");
DisplayInfo(peopleList);
// 方法1 使用IComparer<T>接口。
peopleList.Sort(new PeopleComparer());
// 方法2 除以上兩種方法以外還可以使用另一種方法,在People類中實現(xiàn)IComparable<T>
peopleList.Sort();
System.Console.WriteLine("方法3排序后數(shù)據(jù):");
DisplayInfo(peopleList);
// 方法3 創(chuàng)建泛型委托實例并綁定
Comparison<People> MyComparison = PeopleComparison;
// 傳入該實例實現(xiàn)比較方法
peopleList.Sort(MyComparison);
System.Console.WriteLine("方法3排序后數(shù)據(jù):");
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;
}
}
} 到此這篇關(guān)于C# List.Sort排序(默認排序和自定義排序)的文章就介紹到這了,更多相關(guān)C# List.Sort排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用C#實現(xiàn)Windows組和用戶管理的示例代碼
這篇文章主要介紹了使用C#實現(xiàn)Windows組和用戶管理的示例代碼,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-01-01
C#使用ToUpper()與ToLower()方法將字符串進行大小寫轉(zhuǎn)換的方法
這篇文章主要介紹了C#使用ToUpper()與ToLower()方法將字符串進行大小寫轉(zhuǎn)換的方法,實例分析了C#大小寫轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2015-04-04
C#數(shù)值轉(zhuǎn)換-顯式數(shù)值轉(zhuǎn)換表(參考)
就是在將一種類型轉(zhuǎn)換成另外一種類型時,需要額外的代碼來完成這種轉(zhuǎn)換。2013-04-04
C#對圖片進行馬賽克處理可控制模糊程度的實現(xiàn)代碼
本文通過實例代碼給大家介紹了C#對圖片進行馬賽克處理可控制模糊程度的實現(xiàn)方法,代碼超簡單,具有一定的參考借鑒價值,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05

