输出结果:
升序排列结果. 整形数据:1 整形数据:2 整形数据:3 整形数据:4 整形数据:5 整形数据:6 整形数据:7 整形数据:8 整形数据:9 降序排列结果. 整形数据:9 整形数据:8 整形数据:7 整形数据:6 整形数据:5 整形数据:4 整形数据:3 整形数据:2 整形数据:1除了上述的基本排序以外,有的时候我们可能会有几个条件一起进行排序操作,例如先按照年龄排序,之后再按照成绩排序。这个时候就可以使用到 IEnumerable<T>.ThenBy() 和 IEnumerable<T>.ThenByDescending() 来继续进行排序。
标准用法:
public class Student { public string Name { get; set; } public int Age { get; set; } public int Score { get; set; } } void Main() { // 初始化数据 var students = new List<Student> { new Student{Name="张三",Age=14,Score=120}, new Student{Name="李四",Age=17,Score=80}, new Student{Name="王二",Age=11,Score=170}, new Student{Name ="孙五",Age=21,Score=145} }; // 首先按照成绩降序排序,然后按照年龄升序排序 Console.WriteLine("使用 Then XX 方法进行排序。"); var result = students.OrderByDescending(student=>student.Score).ThenBy(student=>student.Age); // 输出排序结果 Output(result); // 如果不使用 ThenXX 进行排序,而直接使用 OrderXX 进行多个排序条件排序结果 Console.WriteLine("没有使用 Then XX 方法进行排序。"); var newResult = students.OrderByDescending(student => student.Score).OrderBy(student => student.Age); Output(newResult); void Output(IEnumerable<Student> outputStudents) { foreach (var student in outputStudents) { Console.WriteLine($"学生名称:{student.Name},学生年龄:{student.Age},学生成绩:{student.Score}"); } } }输出结果:
使用 Then XX 方法进行排序。 学生名称:王二,学生年龄:11,学生成绩:170 学生名称:孙五,学生年龄:21,学生成绩:145 学生名称:张三,学生年龄:14,学生成绩:120 学生名称:李四,学生年龄:17,学生成绩:80 没有使用 Then XX 方法进行排序。 学生名称:王二,学生年龄:11,学生成绩:170 学生名称:张三,学生年龄:14,学生成绩:120 学生名称:李四,学生年龄:17,学生成绩:80 学生名称:孙五,学生年龄:21,学生成绩:145可以看到如果没有使用 ThenBy() 方法排序的结果,第一个条件根本没有起作用。所以在使用 LINQ 对序列进行排序的时候应该注意这一点,否则得到的结果可能与预期的不一样。
5. IEnuemrable<T>.GroupBy()IEnumerable<T>.GroupBy() 方法主要用于将序列按照指定的列进行分组,这样我们就可以很方便对这些结果进行处理。
IEnumerable<T>.GroupBy() 方法一样是拥有八种不同参数的重载,但按照工作方式来说只有四类,只是每一类都会有一个支持 comparer 比较器的重载。
下面的例子列举了不同重载的使用方法:
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);keySelector 指定的是分组所需要的的列/属性,最后的结果会是一个分组结果的序列。这个序列的值是使用 TKey 和 TSource 组成的分组结果,TKey 指代的是用作分组的列/属性,而 TSource 也是一个序列,存储的是这个分组下的结果。
方法 1
标准用法:
public class Student { public string Name { get; set; } public bool Graduation { get; set; } public int Age { get; set; } public int Score { get; set; } public string City { get; set; } public override string ToString() { return $"姓名:{Name},年龄:{Age},分数:{Score},是否毕业:{Graduation},城市:{City}"; } } class Program { static void Main(string[] args) { var students = new List<Student> { new Student{Name = "张三",Age = 15,Score = 94,Graduation = true,City = "北京"}, new Student{Name = "李四",Age = 17,Score = 47,Graduation = false,City = "北京"}, new Student{Name = "王二",Age = 19,Score = 77,Graduation = false,City = "广州"}, new Student{Name = "孙五",Age = 14,Score = 14,Graduation = false,City = "上海"} }; var groupByResult = students.GroupBy(x => x.City); foreach (var item in groupByResult) { Console.WriteLine($"分组城市:{item.Key}"); foreach (var student in item) { Console.WriteLine(student.ToString()); } } } }输出结果:
分组城市:北京 姓名:张三,年龄:15,分数:94,是否毕业:True,城市:北京 姓名:李四,年龄:17,分数:47,是否毕业:False,城市:北京 分组城市:广州 姓名:王二,年龄:19,分数:77,是否毕业:False,城市:广州 分组城市:上海 姓名:孙五,年龄:14,分数:14,是否毕业:False,城市:上海方法 2
public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);其第一个参数的意思与之前一样,用于指定分组条件。第二个 elementSelector 参数则是与 Select() 方法类似,可以指定输出的分组结果类型。