本文繼續講解List<T>之排序操作,C#范型List類的Sort方法有四種形式,分別是:
1、不帶有任何參數的Sort方法----Sort();
2、帶有比較器參數的Sort方法 ----Sort(IComparer<T>)
3、帶有比較代理方法參數的Sort方法----Sort(Comparison<(Of <(T>)>))
4、帶有比較起參數,可以指定排序范圍的Sort方法----Sort(Int32, Int32 IComparer(T))
首先對IComparable.CompareTo 方法進行一下介紹:
MSDN解釋:將當前實例與同一類型的另一個對象進行比較,並返回一個整數,該整數指示當前實例在排序順序中的位置是位於另一個對象之前、之后還是與其位置相同。
原型:int CompareTo (Object obj)
參數 obj:與此實例進行比較的對象。
返回值:一個 32 位有符號整數,指示要比較的對象的相對順序。
返回值的含義如下:
小於0 此實例小於 obj;位置在obj之前。
等於0 此實例等於 obj;位置在obj相同。
大於0 此實例大於 obj;位置在obj之后。
下面我們通過一個控制台實例來分別介紹這四種方法:
第一種方法元素繼承IComparable:
* 使用這種方法不是對List中的任何元素對象都可以進行排序
* List中的元素對象必須繼承IComparable接口並且要實現IComparable接口中的CompareTo()方法
* 在CompareTo()方法中要自己實現對象的比較規則
我們還沿用第一篇的實體類Player 並使其繼承IComparable接口
using System; namespace ListDemo2 { public class Player : IComparable<Player> { public Player(int id, string name, string team) { this.Id = id; this.Name = name; this.Team = team; } public int Id { get; set; } public string Name { get; set; } public string Team { get; set; } #region IComparable<Model> 成員 /// <summary> /// 實現的IComparable接口,用於進行比較。因為排序是建立在比較的基礎之上的。 /// </summary> /// <param name="otherP">另外一個Player</param> /// <returns> /// 小於0 此實例按排序順序在 otherP 前面 /// 等於0 此實例與otherP 在排序順序中出現的位置相同 /// 大於0 此實例按排序順序在 otherP 后面 /// </returns> public int CompareTo(Player otherP) { //只要調換位置就可以調整排序的方式 //return this.Id.CompareTo(otherP.Id); //正序 return otherP.Id.CompareTo(this.Id); //倒序 } #endregion } }
定義一個集合類PlayerList
using System.Collections.Generic; namespace ListDemo2 { public class PlayerList : List<Player> { public PlayerList() { this.Add(new Player(1, "科比-布萊恩特", "湖人隊")); this.Add(new Player(2, "保羅-加索爾", "湖人隊")); this.Add(new Player(3, "拉瑪爾-奧多姆", "湖人隊")); this.Add(new Player(4, "德克-諾維茨基", "小牛隊")); this.Add(new Player(5, "傑森-特里", "小牛隊")); this.Add(new Player(6, "肖恩-馬里昂", "小牛隊")); this.Add(new Player(7, "凱文-加內特", "凱爾特人隊")); } } }
Main函數代碼:
using System; using System.Collections.Generic; namespace ListDemo2 { class Program { static void Main(string[] args) { //1、不帶有任何參數的Sort方法 PlayerList players = new PlayerList(); Action<Player> listSort = delegate(Player p) { Console.WriteLine(string.Format("隊員Id={0} | 隊員名稱={1} | 所屬球隊={2} ", p.Id, p.Name, p.Team)); }; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("第一種不帶有任何參數的Sort方法"); Console.WriteLine("實現元素繼承ICompare實現_隊員ID從大到小排列:"); Console.ForegroundColor = ConsoleColor.Yellow; players.Sort(); players.ForEach(listSort); Console.ReadKey(); } } }
執行結果如下圖:
第二種帶有比較器參數的Sort方法
* List中的元素對象不需要繼承IComparable接口
* 但需要額外創建一個對象的比較器
我們重新定義個Student 實體類:
namespace ListDemo2 { public class Student { public Student(int id, string name, float score) { this.Id = id; this.Name = name; this.Score = score; } public int Id { get; set; } public string Name { get; set; } public float Score { get; set; } }
再定義個StudentList集合類:
using System.Collections.Generic; namespace ListDemo2 { public class StudentList : List<Student> { public StudentList() { this.Add(new Student(1, "小明", 88.5f)); this.Add(new Student(2, "小紅", 90)); this.Add(new Student(3, "小蘭", 93)); this.Add(new Student(4, "小花", 72.5f)); this.Add(new Student(5, "小貓", 88)); this.Add(new Student(6, "小狗", 63)); } } }
我們定義一個StudentCompare類繼承 IComparer接口:
using System; using System.Collections.Generic; namespace ListDemo2 { public class StudentCompare : IComparer<Student> { //比較器的枚舉,可以按照Id 和 Score 進行排序 public enum CompareType { Id, Score } private CompareType compareType; public StudentCompare(CompareType compareType) { this.compareType = compareType; } public int Compare(Student x, Student y) { if ((x == null) || (y == null)) return -1; switch (compareType) { case CompareType.Id: return x.Id.CompareTo(y.Id); //成績從大到小排列 case CompareType.Score: return y.Score.CompareTo(x.Score); default: return -1; } } } }
Main函數代碼:
using System; using System.Collections.Generic; namespace ListDemo2 { class Program { static void Main(string[] args) { //2、帶有比較器參數的Sort方法 ---Sort(IComparer<T>) StudentList students1 = new StudentList(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("第二種帶有比較器參數的Sort方法"); Console.WriteLine("實現_學生成績從大到小排列:"); Console.ForegroundColor = ConsoleColor.Yellow; students1.Sort(new StudentCompare(StudentCompare.CompareType.Score)); students1.ForEach(s => Console.WriteLine(string.Format("Id={0} | 姓名={1} | 成績={2} ", s.Id, s.Name, s.Score))); Console.ReadKey(); } } }
執行結果如下圖:
第三種方法需要編寫一個對象排序比較的方法
* 對List中的元素對象沒有特殊的要求
* 但在比較方法中需要實現對象比較規則
* 這個方法實現后,就可以把這方名字作為參數委托給List的Sort方法
* Sort方法在排序時會執行這個方法對List中的對象進行比較
我們寫個為學生成績從小到大排序的比較方法:
private static int SortStudentCompare(Student stu1, Student stu2) { return stu1.Score.CompareTo(stu2.Score); }
Main 函數代碼:
using System; using System.Collections.Generic; namespace ListDemo2 { class Program { static void Main(string[] args) { //3、帶有比較代理方法參數的Sort方法 StudentList student2 = new StudentList(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("帶有比較代理方法參數的Sort方法"); Console.WriteLine("實現_學生成績從小到大排列:"); Console.ForegroundColor = ConsoleColor.Yellow; student2.Sort(SortStudentCompare); student2.ForEach(s => Console.WriteLine(string.Format("Id={0} | 姓名={1} | 成績={2} ", s.Id, s.Name, s.Score))); Console.ReadKey(); } } }
執行結果如圖:
第四種方法其實是一種擴展,可以對List內部分數據進行排序
比如我們可以為StudentList的前三名學生的成績進行從大到小的排序:
using System; using System.Collections.Generic; namespace ListDemo2 { class Program { static void Main(string[] args) { //4、帶有比較起參數,可以指定排序范圍的Sort方法 StudentList student3 = new StudentList(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("帶有比較起參數,可以指定排序范圍的Sort方法"); Console.WriteLine("實現_前3名學生成績從大到小排列:"); Console.ForegroundColor = ConsoleColor.Yellow; student3.Sort(0, 3, new StudentCompare(StudentCompare.CompareType.Score)); student3.ForEach(s => Console.WriteLine(string.Format("Id={0} | 姓名={1} | 成績={2} ", s.Id, s.Name, s.Score))); Console.ReadKey(); } } }
執行結果如下圖: