先看下面类:
public class StockQuantity
{
public StockQuantity(string status, DateTime dateTime, int quantity)
{
Status = status;
DateTime = dateTime;
Quantity = quantity;
}
public string Status { get; set; }
public DateTime DateTime { get; set; }
public int Quantity { get; set; }
}
该对象,主要有三个字段,现在的业务需求是,取到了一个类型为List<StockQuantity>集合StockQuantities,需要对该集合进行三次排序,排序规则及优先级如下:
场景1. Status为空的排在后面,不为空的排在前面,不关心Status的内容,只关心Status是否为空。
场景2. DateTime升序排序后Quantity升序排序
小白的做法:
只知道可以对集合用OderBy排序,场景1设计思路如下。
StockQuantities.OrderBy(u=>u.Status)
错误,该排序得规则不仅仅会考虑Status是否为空,还会考虑Status的内容。如果Status是[“b”,”c”,null,”d”],那么排序结果是[null,“b”,”c”,”d”]。而我们要的结果是[“b”,”c”,”d” ,null] (直接把null的丢到后,别的不动)怎么办?
暂时不知道,先不管
场景2:
对日期(DateTime)排序后再对质量(Quantity)排序的话,用OrderBy,也就是
StockQuantities.OrderBy(u=>u.DateTime).OrderBy(u=>u.Quantity)
但是这样结果一定是错误的
以上表达式等同于下面两条的表达式:
StockQuantities = StockQuantities.OrderBy(u=>u.DateTime)
StockQuantities = StockQuantities.OrderBy(u=>u.Quantity)
所以句代码没有任何意义,终排序还是以质量(Quantity)进行排序的。
正确的做法:
先说一下条件排序和多级排序。
什么是条件排序,怎么用,场景1的代码直接改为。
StockQuantities.OrderBy(u=>u.Status==null)
这就是条件排序,可是咋一看,给人一种是把Status为空的排前面,不为空的排后面的错觉。
其实不然,我们看到OrderBy里面的一个返回值为bool类型的表达式,该排序先排结果为0(false)的,再排结果为1(true)的,0排前面,1排后面,这种排序只考虑返回的bool值,不考虑参数的具体值,所以姑且称它为条件排序,完全符合排序场景1的要求。
什么是多级排序,怎么用,场景2的代码改为如下:
stockQuantities = stockQuantities.OrderBy(u => u.Status==null).ThenBy(u => u.DateTime).ThenBy(u => u.Quantity).ToList();
连续地使用多个OrderBy终只会生效后一个OrderBy,这个时候应该使用ThenBy,即可完美地实现再前一个排序前提下进行二级排序。
优化后的完整代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
namespace OrderBy
{
class Program
{
static void Main(string[] args)
{
var stockQuantities = new List
{
new StockQuantity("正常品",new DateTime(2017,4,16),12 ),
new StockQuantity("正常品",new DateTime(2017,4,17),15 ),
new StockQuantity("残次品",new DateTime(2017,4,16),10 ),
new StockQuantity("残次品",new DateTime(2017,4,17),8 ),
new StockQuantity(null,new DateTime(2017,4,18),8 ),
};
stockQuantities = stockQuantities.OrderBy(u => u.Status==null).ThenBy(u => u.DateTime).ThenBy(u => u.Quantity).ToList();
foreach (var stockQuantity in stockQuantities)
{
Console.WriteLine($"{stockQuantity.Status}-{stockQuantity.DateTime}-{stockQuantity.Quantity}");
}
Console.ReadKey();
}
}
public class StockQuantity
{
public StockQuantity(string status, DateTime dateTime, int quantity)
{
Status = status;
DateTime = dateTime;
Quantity = quantity;
}
public string Status { get; set; }
public DateTime DateTime { get; set; }
public int Quantity { get; set; }
}
}
简单的一个排序优化,牵扯到一些基础知识点,所以在这里把这排序技巧分享出来,希望对不会的同学有所帮助。