List排序Sort和OrderBy方法(C#)

本文对比了C#中List的Sort和OrderBy方法,Sort结合了快速排序、插入排序和堆排序,可能改变列表顺序;而OrderBy使用快速排序,保持列表顺序。文章通过示例详细介绍了如何使用OrderBy和Sort进行排序,包括实现IComparer、IComparable接口以及使用Comparison委托。最后指出,大数据量排序推荐使用Sort的扩展方法,小数据量场景下OrderBy更简洁。

Sort和OrderBy的定义比较

1、List.Sort()排序:
Sort并不是简单的快速排序,它对普通的快速排序进行了优化,它还结合了插入排序和堆排序。系统会根据你的数据形式和数据量自动选择合适的排序方法,这并不是说它每次排序只选择一种方法,它是在一次完整排序中不同的情况选用不同方法,比如给一个数据量较大的数组排序,开始采用快速排序,分段递归,分段之后每一段的数据量达到一个较小值后它就不继续往下递归,而是选择插入排序,如果递归的太深,他会选择堆排序。

说明:
  a. 使用Sort排序时,有可能会打破数组列表的基本顺序。在数据相同的项具有不同含义时,不能使用Sort排序;
  b. Array.Sort和List.Sort采用的是同一个排序方法。
  
2、Linq.Orderby()排序:使用快速排序,不会破坏数组列表的基本顺序。

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。3.再对左右区间重复第二步,直到各区间只有一个数。《菜鸟教程》

应用示例

对于纯Int或者double类型的List,可以直接使用List.Sort()或者List.Reverse()进行升序或降序排序操作。

对于非基本类型的排序,我们先做出下面的一个示例

先创建一个自定义类型

public class Student
    {
        public double Score { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

然后创建一个实例

List<Student> stuList = new List<Student>()
            {
                new Student(){Score = 90,Name="Tim",Age=29},
                new Student(){Score = 98,Name="Tom",Age=28},
                new Student(){Score = 98,Name="Tomi",Age=23},
                new Student(){Score = 82,Name="Kyle",Age=27},
                new Student(){Score = 76,Name="Tony",Age=26},
                new Student(){Score = 96,Name="moly",Age=39},
                new Student(){Score = 86,Name="Tkiy",Age=29},
                new Student(){Score = 97,Name="Vina",Age=25},
                new Student(){Score = 95,Name="Mike",Age=24},
                new Student(){Score = 95,Name="Coki",Age=29},
            };

一、使用OrderBy方法排序

我们先将StuList用Score排序,然后用Age排序 ,这里使用Lambda表达式

List<Student> list1 =  stuList.OrderBy(t => t.Score).ThenBy(x=>x.Age).ToList();//升序
List<Student> list1 =  stuList.OrderByDescending(t => t.Score).ThenByDescending(x=>x.Age).ToList();//降序

二、使用Sort方法排序

查看Sort的源码可以发现它有如下的几个重载:

public void Sort(); 
public void Sort(IComparer<T> comparer);   
public void Sort(Comparison<T> comparison);     
public void Sort(int index, int count, IComparer<T> comparer);     
  1. 不带有任何参数的Sort方法----Sort();
  2. 带有比较器参数的Sort方法 ----Sort(IComparer)
  3. 带有比较代理方法参数的Sort方法----Sort(Comparison<(Of <(T>)>))
  4. 带有比较器参数,可以指定排序范围的Sort方法----Sort(Int32, Int32 IComparer(T))

1、实现IComparer接口

在自定义类型里实现IComparer接口,此处要注意:返回值,小于0代表x < y,等于0代表x=y,大于0代表x > y.

public class Student : IComparer<Student>
    {
        public double Score { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public int Compare(Student x, Student y)
        {
            if (x.Score == y.Score && x.Age == y.Age)
            {
                return 0;
            }
            else
            {
                if (x.Score.CompareTo(y.Score) > 0)
                {
                    return 1;
                }
                else if (x.Score == y.Score && x.Age > y.Age)
                {
                    return 1;
                }
                else
                {
                    return -1;
                }
            }
        }
    }

调用

IComparer<Student> comparer = new Student();
 stuList.Sort(comparer);

2、实现IComparable接口

在自定义类型里实现IComparable接口,此处要注意:返回值,小于0代表x < y,等于0代表x=y,大于0代表x > y 只是与上面一个方法的调用形式不一样。

public class Student : IComparable<Student>
    {
        public double Score { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public int CompareTo(Student other)
        {
            if (null == other)
            {
                return 1;
            }
            int re = this.Score.CompareTo(other.Score);
            if (0 == re)
            {
                return this.Age.CompareTo(other.Age);
            }
            return re;
        }
    }

调用

stuList.Sort();

3、使用Comparison委托

查看Comparison的源码可以发现,Comparison委托的定义如下:

public delegate int Comparison<in T>(T x, T y);

使用委托,可以传递一个与委托签名相同的函数,可以使用匿名委托,还可以用Lambda表达式:

使用匿名委托调用:

stuList.Sort(delegate (Student x, Student y)
            {
                if (x.Score == y.Score && x.Age == y.Age)
                {
                    return 0;
                }
                else
                {
                    if (x.Score.CompareTo(y.Score) > 0)
                    {
                        return 1;
                    }
                    else if (x.Score == y.Score && x.Age > y.Age)
                    {
                        return 1;
                    }
                    else
                    {
                        return -1;
                    }
                }
            });

对于List的排序,也就是实现接口、使用委托,OrderBy方法,lambda表达式只是让形式更简单,并不能达到加快速度的效果。

结论:对于大数据量的数据排序,建议使用Sort()的扩展方法来实现,如果是小数据量,则直接使用OrderBy()方法更为简洁。

<think>我们正在讨论C#List<T>的排序方法。根据引用[1][2],我们可以知道List<T>.Sort()方法使用不同的排序算法,并且支持自定义比较器。同时,引用[3]中提到了LINQ中的排序方法(如OrderBy),但用户问题明确是关于List排序方法,因此我们将重点放在List<T>自带的排序方法上。 我们将从以下几个方面进行说明: 1. 默认排序(无参数Sort) 2. 使用自定义比较器(IComparer<T>) 3. 使用Comparison委托 4. 使用LINQ进行排序(虽然属于LINQ,但也是常见的对List排序的方式) 5. 性能注意事项 注意:引用[1]提到,Sort方法内部根据情况选择不同的排序算法(如插入排序快速排序、归并排序等),但具体实现由.NET框架决定,我们只需知道其平均时间复杂度为O(n log n),最坏情况为O(n^2)(但实际中会尽量避免)。 下面详细说明:</think>### C# List 排序方法使用指南 在 C# 中,`List<T>` 提供了多种排序方式,根据数据类型需求可选择不同方法。以下是核心排序方法详解: --- #### 一、**基础排序方法** 1. **`Sort()` 无参方法** - **作用**:对实现了 `IComparable<T>` 接口的元素进行默认升序排序 - **示例**: ```csharp List<int> numbers = new List<int> { 5, 2, 8, 1 }; numbers.Sort(); // 结果:{ 1, 2, 5, 8 } ``` - **适用类型**:基本类型(`int`, `string` 等)或自定义类实现 `IComparable<T>`[^1] 2. **`Sort(IComparer<T>)` 自定义比较器** - **作用**:通过传入比较器对象实现灵活排序逻辑 - **示例**(按字符串长度排序): ```csharp public class LengthComparer : IComparer<string> { public int Compare(string x, string y) => x.Length.CompareTo(y.Length); } List<string> words = new List<string> { "apple", "kiwi", "banana" }; words.Sort(new LengthComparer()); // 结果:{ "kiwi", "apple", "banana" } ``` [^2] --- #### 二、**高级排序技巧** 1. **Lambda 表达式快速排序** - 使用 `Comparison<T>` 委托简化代码: ```csharp List<Product> products = GetProducts(); products.Sort((p1, p2) => p1.Price.CompareTo(p2.Price)); // 按价格升序 ``` 2. **多条件排序** - 组合 `ThenBy` 实现(需转换为 `IOrderedEnumerable`): ```csharp var sorted = products .OrderBy(p => p.Category) .ThenByDescending(p => p.Price) .ToList(); // 先按分类升序,再按价格降序 ``` [^3] 3. **LINQ 排序** - 使用 `OrderBy`/`OrderByDescending`: ```csharp List<int> nums = new List<int> { 10, 3, 7 }; var sortedNums = nums.OrderBy(n => n).ToList(); // { 3, 7, 10 } ``` - **优点**:返回新列表(不修改原列表),支持链式调用[^3] --- #### 三、**性能与算法解析** | 方法 | 时间复杂度 | 适用场景 | |--------------------|-------------------|----------------------------------| | `Sort()` | $O(n \log n)$ 平均 | 通用排序(小列表可能用插入排序)[^1] | | `OrderBy()` (LINQ) | $O(n \log n)$ | 需保留原列表或链式操作时 | | 自定义比较器 | 同 `Sort()` | 复杂对象或多条件排序 | > **注意**: > - 对大型列表(>1000元素),`Sort()` 通常比 LINQ 的 `OrderBy()` 更快(因 `OrderBy` 需额外内存) > - 值类型排序比引用类型更快(无装箱开销) --- #### 四、**完整示例:自定义类排序** ```csharp public class Student : IComparable<Student> { public string Name { get; set; } public int Score { get; set; } // 实现默认比较接口(按分数) public int CompareTo(Student other) => Score.CompareTo(other.Score); } // 使用比较器按姓名排序 public class NameComparer : IComparer<Student> { public int Compare(Student x, Student y) => x.Name.CompareTo(y.Name); } // 调用 List<Student> students = GetStudents(); students.Sort(); // 按分数升序 students.Sort(new NameComparer()); // 按姓名升序 ``` > **最佳实践**: > - 频繁排序场景优先用 `Sort()` > - 只读操作或需多条件排序时用 LINQ > - 避免在循环中重复排序(可缓存结果) --- ### 总结 | 需求场景 | 推荐方法 | |------------------------|----------------------------| | 简单升序排序 | `List.Sort()` | | 复杂或多条件排序 | 自定义 `IComparer<T>` 或 LINQ | | 需保留原列表 | `OrderBy().ToList()` | | 性能敏感的大列表 | `Sort()` + 自定义比较器 | 通过合理选择排序方法,可显著提升代码效率可读性[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值