.Net中集合排序还可以这么玩
背景:
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中集合排序还可以这么玩的更多相关文章
- .Net中集合排序的一种高级玩法
背景: 学生有名称.学号, 班级有班级名称.班级序号 学校有学校名称.学校编号(序号) 需求 现在需要对学生进行排序 第一排序逻辑 按学校编号(序号)排列 再按班级序号排列 再按学生学号排列 当然,在 ...
- sql按in中集合排序
1.SELECT * from tbLabelResRelation WHERE lId in(32,18,27,19) order by FIND_IN_SET(lId ,'32,18,27,19' ...
- .Net中集合排序
public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity) { ...
- C# 中集合类型需要按多个条件排序
在 C# (.net 3.5 之后) 中集合是可以通过 OrderBy() 和 OrderByDescending()方法来进行排序的,如果需要集合中的元素是对象,还可以通过 Lambda表达式进行按 ...
- Java集合中对象排序
集合中的对象排序需求还是比較常见的.当然我们能够重写equals方法,循环比較:同一时候Java为我们提供了更易使用的APIs.当须要排序的集合或数组不是单纯的数字型时,通常能够使用Comparato ...
- Hadoop学习笔记—11.MapReduce中的排序和分组
一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...
- Comparable与Comparator,java中的排序与比较
1:比较和排序的概念 比较:两个实体类之间按>,=,<进行比较. 排序:在集合类中,对集合类中的实体进行排序.排序基于的算法基于实体类提供的比较函数. 基本型别都提供了默认的比较算法,如s ...
- Java集合排序及java集合类详解--(Collection, List, Set, Map)
1 集合框架 1.1 集合框架概述 1.1.1 容器简介 到目前为止,我们已经学习了如何创建多个不同的对象,定义了这些对象以后,我们就可以利用它们来做一 ...
- Java:类集框架中集合的学习
Java:类集框架中集合的学习 集合 Java:Set的学习 Set是类集框架中的集合类.集合是不按特定的方式排序,并且没有重复对象的一种类. Q:Set如何操作?Set中的不按特定方式排序是怎么排序 ...
随机推荐
- 关于JSP页面URL传值所遇到的小问题
在JSP页面中我的页面传值加了分号,在后台取值是没有问题的. 但是在XML底层执行时就会返回不了值,这是什么原因呢? 经过努力排查发现了分号导致了${XXX}的值都成了和前面ID一样的串.去掉${XX ...
- gem devise配置
Step1: Gemfile中加入gem 'devise' Step3: rails g devise:install 这一步执行完后命令行会提醒要手动进行如下动作: ================ ...
- 微信APP简要分析
Part1 走进微信APP 很明显,微信是很成功的APP. 微信 (WeChat) 是腾讯公司于2011年1月21日推出的一个为智能终端提供即时通讯服务的免费应用程序,现已是超过九亿人使用的手机应用. ...
- 201621123050 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 2. 使用数据库技术改造你的系统 2.1 简述如何使用数据库技术改造你的系统.要建立什么表?截图你的表设计. 答 ...
- 高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告
高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告 Deadline:2017-10-30(周一)21:00pm (注:以下内容参考集大作业4,集大作业5,集大作业6,集大作业7 一. ...
- Linux下I/O多路转接之select --fd_set
fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...
- 团队作业4——第一次项目冲刺(Alpha版本)2017.11.14
第一次会议:2017-11-14 额--这几天比较忙,忘记上传了,今天补上 先上个图,O(∩_∩)O哈哈: 会议主要内容: 1. 讨论整体框架 2. 个人具体分工 3. 代码统一 具体分工: 成员 计 ...
- linux系统增加开机启动服务/应用
操作 在/etc/init.d下新建示例脚本文件(customize.sh),该脚本会启动zookeeper服务.内容如下: #!/bin/sh /usr/local/zookeeper-/bin/z ...
- 《javascript设计模式与开发实践》阅读笔记(15)—— 装饰者模式
装饰者模式 可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么我们就可以使用装饰者模式. 代码例 ...
- Python爬虫之urllib模块1
Python爬虫之urllib模块1 本文来自网友投稿.作者PG,一个待毕业待就业二流大学生.玄魂工作室未对该文章内容做任何改变. 因为本人一直对推理悬疑比较感兴趣,所以这次爬取的网站也是平时看一些悬 ...