C#中List<T>排序
在面向对象开发过程中我们经常将一组对象放到一个特定集合中,此时我们通常使用泛型集合来存放,常见的如:List、Dictionary等。在使用这些泛型集合时我们有时需要对其进行排序,下面我们就一起学习下List<T>是如何进行排序的。
1.初始化集合
假如我们有一个Student对象,简单起见这个对象只有三个属性,分别是学号、姓名、年龄。
namespace YDSLM_KT_SYSTEM.App_Code.Model
{
public class Student
{
public Student() { }
public Student(string stuNo, string stuName, int stuAge)
{
this.StuNo = stuNo;
this.StuName = stuName;
this.StuAge = stuAge;
}
public string StuNo { get; set; }
public string StuName { get; set; }
public int StuAge { get; set; }
}
}
我们有四个学生,分别存放在List中。
using System;
using System.Collections.Generic;
namespace YDSLM_KT_SYSTEM
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<App_Code.Model.Student> Students = new List<App_Code.Model.Student>();
Students.Add(new App_Code.Model.Student("00001", "张三", 17));
Students.Add(new App_Code.Model.Student("00002", "李四", 16));
Students.Add(new App_Code.Model.Student("00003", "王五", 18));
Students.Add(new App_Code.Model.Student("00004", "尔玛", 17));
Response.Write("未进行排序前:<br />");
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:
{1} 年龄:{2}<br />", stu.StuNo,
stu.StuName, stu.StuAge));
}
}
}
}

很明显我们往Students对象中加入的时候并没有按年龄顺序,下面我们就一起看一下如何对Students集合按照年龄由小到大来排序。
2.默认排序方式
如果你查一下List<T>的API的话,我们会看到对于List的Sort方法有四种重载,首先在这里我们说一下第一种,也就是无参数的情况:List.Sort()。那么我能不能直接对Students集合使用Sort()方法进行排序呢?答案是否定的,如果我们使用下面的方法排序的话系统将抛出System.ArgumentException异常。

从图中的提示我们可以看出错误原因是由于进行比较的对象并未有任何一个实现IComparable接口,因此也就无法完成排序。事实上对于参数Sort()方法是使用Comparer.Default比较器来排序的,而此比较器进行比较时首先就会检查T是否实现了IComparable泛型接口,如果实现了则使用该实现。否则将坚持是否实现了IComparable接口。如果均未实现则引发InvalidOperationException异常。也就是说如果想使用此方法需要实现IComara泛型接口或者IComparable接口,因此我们暂且修改一下Student类,实现IComparable接口(除了这个例子职务后面的例子仍然使用第一步我们建立的Student类)。
首先修改Student类,实现IComparable接口:
using System;
namespace YDSLM_KT_SYSTEM.App_Code.Model
{
public class Student : IComparable
{
public Student() { }
public Student(string stuNo, string stuName, int stuAge)
{
this.StuNo = stuNo;
this.StuName = stuName;
this.StuAge = stuAge;
}
public string StuNo { get; set; }
public string StuName { get; set; }
public int StuAge { get; set; }
#region IComparable接口成员
public int CompareTo(object obj)
{
if (obj is Student)
{
Student tempStu = obj as Student;
return this.StuAge.CompareTo(tempStu.StuAge);
}
throw new NotImplementedException("obj is not a Student!");
}
#endregion
}
}
然后我们再运行程序就会看到可以按照我们的想法去排序了。
接着再使用Sort()排序的话就可以看到如下排序成功的界面:

3.通过自定义比较器进行排序
尽管我们上面说过可以使用Sort()方法排序,但是要求Student必须实现IComparable泛型接口,那么我们有没有其他的方法呢?其实是有的,个人感觉这种方法多数情况下会更好一些。那就是:List.Sort(泛型Comparison)和List.Sort(泛型IComparer)方法。之所以将这两种重载放到一起来说,是因为二者使用范围上很类似。首先看一下List.Sort(泛型Comparison)方法,此方法的参数是Comparison类型,其实是一个包含两个参数的委托,因此使用此方法,我们只需要定义一个委托,其两个参数均为Student类型,在委托实现的方法比较两个Student对象Age属性即可。
using System;
using System.Collections.Generic;
namespace YDSLM_KT_SYSTEM
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<App_Code.Model.Student> Students = new List<App_Code.Model.Student>();
Students.Add(new App_Code.Model.Student("00001", "张三", 17));
Students.Add(new App_Code.Model.Student("00002", "李四", 16));
Students.Add(new App_Code.Model.Student("00003", "王五", 18));
Students.Add(new App_Code.Model.Student("00004", "尔玛", 17));
Response.Write("未进行排序前:<br />");
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
Response.Write("使用List.Sort(泛型Comparison)排序之后:<br />");
Students.Sort(delegate(App_Code.Model.Student a, App_Code.Model.Student b)
{
return a.StuAge.CompareTo(b.StuAge);
});
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
}
}
}
运行结果(注意:此时以及下面的所有例子中Student均不需要实现IComparable泛型接口):

接着我们看一下List.Sort(泛型IComparer),此方法需要一个泛型IComparer接口类型,因此只要定义一个类实现此接口然后再调用此方法即可。
using System.Collections.Generic;
namespace YDSLM_KT_SYSTEM.App_Code
{
public class StudentCompare:IComparer<Model.Student>
{
public int Compare(Model.Student x, Model.Student y)
{
return x.StuAge.CompareTo(y.StuAge);
}
}
}
-----------------------------------------------------
using System;
using System.Collections.Generic;
namespace YDSLM_KT_SYSTEM
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<App_Code.Model.Student> Students = new List<App_Code.Model.Student>();
Students.Add(new App_Code.Model.Student("00001", "张三", 17));
Students.Add(new App_Code.Model.Student("00002", "李四", 16));
Students.Add(new App_Code.Model.Student("00003", "王五", 18));
Students.Add(new App_Code.Model.Student("00004", "尔玛", 17));
Response.Write("未进行排序前:<br />");
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
Response.Write("使用List.Sort (泛型 IComparer) 排序之后:<br />");
Students.Sort(new App_Code.StudentCompare());
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
}
}
}
运行结果:

4.设定排序范围
虽然上面的方法都实现了泛型List<T>集合排序,但是有时我们并不需要对整个集合进行排序而是指对其中一定范围的对象进行排序,那么我们就需要使用Sort方法的第四种重载:List.Sort(int32,int32,泛型IComparer)。前两个参数分别代表排序的其实位置和排序长度,最后一个参数仍然是泛型IComparer接口类型。上面我们已经定义了StudentComparer类,实现了IComparer接口,这里就可以直接使用了,下面我们只对前三个学生按年龄由小到大进行排序。
using System;
using System.Collections.Generic;
namespace YDSLM_KT_SYSTEM
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<App_Code.Model.Student> Students = new List<App_Code.Model.Student>();
Students.Add(new App_Code.Model.Student("00001", "张三", 17));
Students.Add(new App_Code.Model.Student("00002", "李四", 16));
Students.Add(new App_Code.Model.Student("00003", "王五", 18));
Students.Add(new App_Code.Model.Student("00004", "尔玛", 17));
Response.Write("未进行排序前:<br />");
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
Response.Write("使用List.Sort (Int32, Int32, 泛型 IComparer) 排序之后:<br />");
Students.Sort(0, 3, new App_Code.StudentCompare());
foreach (App_Code.Model.Student stu in Students)
{
Response.Write(string.Format("学号:{0} 姓名:{1} 年龄:{2}<br />", stu.StuNo, stu.StuName, stu.StuAge));
}
}
}
}
运行效果:

到这里我和大家一起学习分享完毕了,期望对大家也有些帮助!!!
C#中List<T>排序的更多相关文章
- 禁用datagridview中的自动排序功能
把datagridview中的自动排序功能禁用自己收集的两种方法,看看吧①DataGridView中的Columns属性里面可以设置.进入"EditColumns"窗口后,在相应的 ...
- mapreduce任务中Shuffle和排序的过程
mapreduce任务中Shuffle和排序的过程 流程分析: Map端: 1.每个输入分片会让一个map任务来处理,默认情况下,以HDFS的一个块的大小(默认为64M)为一个分片,当然我们也可以设置 ...
- 在C#中对Datatable排序【DefaultView的Sort方法】
在C#中对Datatable排序,[DefaultView的Sort方法] 代码如下: DataTable dt = new DataTable(); dt.Columns.Add("ID& ...
- php中数组自定义排序
php中数组自定义排序方法有很多,现在只提usort();不会保留原有键名. unsort调用方法就是unsrot($arr,func); 注意: 如果func是写在当前类中的话,那么调用的方式是 u ...
- 关于Oracle数据库中SQL空值排序的问题
在Oracle中进行查询排序时,如果排序字段里面有空值的情况下,排序结果可能会达不到自己想要的结果. 如 select * from tableTest order by VISITS desc ...
- Java基础知识强化之IO流笔记52:IO流练习之 把一个文件中的字符串排序后再写入另一个文件案例
1. 把一个文件中的字符串排序后再写入另一个文件 已知s.txt文件中有这样的一个字符串:"hcexfgijkamdnoqrzstuvwybpl" 请编写程序读取数据内容,把数据排 ...
- DataSet 中的数据排序 及 DataRow装成DataTable
1.DataSet 中的数据排序 DataSet ds = new DataSet(); // 获取当前排口的数据 ds = _xiaobill.GetHistoryData(yinZiBianm, ...
- Python中的选择排序
选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大 ...
- python中的列表排序
对列表进行排序是常见的操作,最简单的方式是使用sort()函数. 1.一般用法 不管列表元素是数.字符串还是元组,函数sort()总是就地操作列表,按升序进行排列元素,并返回None. #数 > ...
- MySQL中order by排序时,数据存在null咋办
order by排序是最常用的功能,但是排序有时会遇到数据为空null的情况,这样排序就会乱了,这里以MySQL为例,记录我遇到的问题和解决思路. 问题: 网页要实现table的行鼠标拖拽排序,我用A ...
随机推荐
- C#中webbrowser与javascript(js)交互的方法
今天在做一个项目的时候需要用c#搞一个webbrowser,然后有些地方还需要与js交互.所以就查了一下资料,发现很多博客提到了但是却没有说下具体的操作.所以我就写一下. 开发环境是Visual St ...
- 【vue】vue +element 搭建项目,点击空白处关闭弹窗
<template> <div class="step2"> <el-button @click="togglePanel($event)& ...
- 002_浅析python 中__name__ = '__main__' 的作用
很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码,可能很多新手一开始学习的时候都比较疑惑,python 中__name__ = ...
- mybatis 中 foreach collection的三种用法(转)
文章转自 https://blog.csdn.net/qq_24084925/article/details/53790287 oreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集 ...
- c# 利用百度图像处理【人像分割】一键抠图
百度AI开放平台-人像分割: http://ai.baidu.com/tech/body/seg 注意本文后面的话,百度这个技术效果太差劲了,国外这 https://www.remove.bg/ 个比 ...
- numpy.loadtxt()
简介 np.loadtxt()用于从文本加载数据. 文本文件中的每一行必须含有相同的数据. loadtxt(fname, dtype=<class 'float'>, comments=' ...
- 移动H5页面微信支付踩坑之旅(微信支付、单页面路由模拟、按钮加锁、轮询等常见功能)
开发背景: .net混合开发的vue模板语法的单页面应用,所以不存在脚手架以及没有路由可以跳转. 项目描述: 需要写两个页面,在订单详情页需要点击“请输入手机号”进入手机号绑定页面,手机号绑定成功后自 ...
- python第五章:文件--小白博客
文件操作, 操作文件完毕后一定要记得close # 读,默认是rt(文本的方式读取),rb模式是以字节读取 # 文件路径可以用3中形式表示 f = open(r'C:\Users\fengzi\Des ...
- 2017百度软研(C++)
问了很多,不过很多也都没有问到,感觉有点偏,很深入的东西,越问越虚.第一次实习面试从百度开始,也从百度结束吧.看得见的差距,不想将就,所以还是拿最后一次机会去尝试.win or go home, 所以 ...
- 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)
lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...