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();
        }
    }
}

 执行结果如下图: 

-=源码下载=-

原文地址:https://www.cnblogs.com/lxblog/p/2652859.html