List集合操作二:排序


本文繼續講解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();
        }
    }
}

 執行結果如下圖: 

-=源碼下載=-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM