背景:

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升序排序。
3.    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进行升序排序,这简单
StockQuantities.OrderBy(u=>u.DateTime)
半对!
为什么半对,看下面

3.    在排序2的前提下,用OrderBy,也就是StockQuantities.OrderBy(u=>u.DateTime).OrderBy(u=>u.Quantity)
错误!
以上表达式等同于下面两条的表达式:

StockQuantities = StockQuantities.OrderBy(u=>u.DateTime)
StockQuantities = StockQuantities.OrderBy(u=>u.Quantity)

所以第一条代码就是废代码,最终排序还是以Quantity进行排序的。
虽然我是小白,但我还是明白这样是错误的,所以我的做法是

stockQuantities = stockQuantities.OrderBy(u => u.DateTime).ToList();

            foreach (var dateOrder in stockQuantities)
{
var datetimeOrderBy = stockQuantities.Where(u => u.DateTime.Date == dateOrder.DateTime.Date) .OrderBy(u => u.Count); foreach (var countOrder in datetimeOrderBy)
{
if (countOrder.OutPut == false)
{
Console.WriteLine($"{countOrder.Status}-{countOrder.DateTime}-{countOrder.Count}");
countOrder.OutPut = true;
} }
}
Console.ReadKey();

采用双层循环,先取到按时间排序的数据 dateOrder,再去和该条数据在同一天的所有数据并对Quantity进行排序,为了防止重复的输出,我同时给StockQuantity对象加上了Output属性,当该属性为false为,则输出该对象的内容,并把Output属性设为true,这样就不会重复输出了,而且实现了先对DateTime排序,再对Quantity进行排序。
So Easy!!
然而,当开心地把这样的代码提交之后,却被同事狠狠地鄙视了,说到:“什么烂代码啊!”然道还有比这更好的代码?

给同事倒了一杯茶,点了一根烟,虚心请教。

大佬做法:

同事给我讲了两招,分别是条件排序、多级排序。

什么是条件排序,怎么用?

1.    StockQuantities.OrderBy(u=>u.Status==null)
这就是条件排序,可是咋一看,给人一种是把Status为空的排前面,不为空的排后面的错觉。
其实不然,我们看到OrderBy里面的一个返回值为bool类型的表达式,该排序先排结果为0(false)的,再排结果为1(true)的。这种排序只考虑返回的bool值,不考虑参数的具体值,所以姑且称它为条件排序。
完全符合排序规则1的要求。

什么是多级排序,怎么用?

2.    利用我上面我的代码排序虽然可以实现先排DateTime,再排Quantity,但是该算法的时间复杂度的n*n,而且给StockQuantity添加了output字段,明显是不科学的。
然而,连续地使用多个OrderBy最终只会生效最后一个OrderBy,天无绝人之路,所以这个时候应该使用ThenBy!!
使用ThenBy可以讲以上的三条排序规则简化如下:
stockQuantities = stockQuantities.OrderBy(u => u.Status==null).ThenBy(u => u.DateTime).ThenBy(u => u.Quantity).ToList();
即可完美地实现再前一个排序前提下进行二级排序。

优化后的完整代码如下:

using System;
using System.Collections.Generic;
using System.Linq; namespace OrderBy
{
class Program
{
static void Main(string[] args)
{
var stockQuantities = new List<StockQuantity>()
{
new StockQuantity("正常品",new DateTime(,,), ),
new StockQuantity("正常品",new DateTime(,,), ),
new StockQuantity("残次品",new DateTime(,,), ),
new StockQuantity("残次品",new DateTime(,,), ),
new StockQuantity(null,new DateTime(,,), ),
}; 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; } }
}

简单的一个排序优化,就把程序的时间复杂度从N*N降低到了N,所以在这里把这两种排序技巧分享出来,希望对不会的同学有所帮助。

.Net中集合排序还可以这么玩的更多相关文章

  1. .Net中集合排序的一种高级玩法

    背景: 学生有名称.学号, 班级有班级名称.班级序号 学校有学校名称.学校编号(序号) 需求 现在需要对学生进行排序 第一排序逻辑 按学校编号(序号)排列 再按班级序号排列 再按学生学号排列 当然,在 ...

  2. sql按in中集合排序

    1.SELECT * from tbLabelResRelation WHERE lId in(32,18,27,19) order by FIND_IN_SET(lId ,'32,18,27,19' ...

  3. .Net中集合排序

    public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity) { ...

  4. C# 中集合类型需要按多个条件排序

    在 C# (.net 3.5 之后) 中集合是可以通过 OrderBy() 和 OrderByDescending()方法来进行排序的,如果需要集合中的元素是对象,还可以通过 Lambda表达式进行按 ...

  5. Java集合中对象排序

    集合中的对象排序需求还是比較常见的.当然我们能够重写equals方法,循环比較:同一时候Java为我们提供了更易使用的APIs.当须要排序的集合或数组不是单纯的数字型时,通常能够使用Comparato ...

  6. Hadoop学习笔记—11.MapReduce中的排序和分组

    一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...

  7. Comparable与Comparator,java中的排序与比较

    1:比较和排序的概念 比较:两个实体类之间按>,=,<进行比较. 排序:在集合类中,对集合类中的实体进行排序.排序基于的算法基于实体类提供的比较函数. 基本型别都提供了默认的比较算法,如s ...

  8. Java集合排序及java集合类详解--(Collection, List, Set, Map)

    1         集合框架 1.1         集合框架概述 1.1.1         容器简介 到目前为止,我们已经学习了如何创建多个不同的对象,定义了这些对象以后,我们就可以利用它们来做一 ...

  9. Java:类集框架中集合的学习

    Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...

随机推荐

  1. Vue常用开源项目汇总

    前言:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还 ...

  2. java排序算法(三):堆排序

    java排序算法(三)堆排序 堆积排序(HeapSort)是指利用堆积树这种结构所设计的排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法.辅助空间为O(1).最坏时间复杂度 ...

  3. Axure RP初学

    制作商品购买页

  4. 实现Windows数据绑定

    dataSet数据集   dataset驻留于内存临时存储数据简单的理解为一个临时数据库将数据源的数据保存在内存中独立于任何数据库创建dataset对象引入命名空间:system.Datadatase ...

  5. va_list va_start va_end va_arg 解决变参问题

    解决参数个数不确定的问题. 头文件 #include<stdarg.h> VA_LIST 是在C语言中解决变参问题的一组宏,用于获取不确定个数的参数. #ifdef _M_ALPHA ty ...

  6. Redis——主从同步原理

    刚接触到Redis,首先对Redis有一个初步的了解. 开源,免费,遵守BSD协议,key-value数据库. 可以将内存中的数据保存在磁盘中,重启的时候可以再次加载使用. 多种key-value类型 ...

  7. Alpha第五天

    Alpha第五天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  8. 和为S的连续正数序列——牛客网(剑指offer)

    题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他 ...

  9. mongodb 集群分片

    分片 在Mongodb里面存在另一种集群,就是分片技术,可以满足MongoDB数据量大量增长的需求 当MongoDB存储海量的数据时,一台机器可能不足以存储数据,也可能不足以提供可接受的读写吞吐量,这 ...

  10. intellij idea 找不到或无法加载主类

    解决intellij idea 找不到或无法加载主类,请看以下图文介绍 然后idea会重启,等idea启动后 右侧的maven clean 一下,然后再compile就解决了