.Net中的集合排序可以这么玩你知道吗

C#集合类型概述

集合是.NET FCL(Framework Class Library)中很重要的一部分。所有的集合类都继承自IEnumerable。集合类总体可分为一下几类:关联/非关联型集合,顺序/随机访问集合,顺序/无序集合,泛型/非泛型集合,线程安全集合。

各集合类底层接口关系图

背景:

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(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; }
 }
}

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

您可能感兴趣的文章:

  • 关于.NET的集合总结
  • asp.net php asp jsp 301重定向的代码(集合)
(0)

相关推荐

  • 关于.NET的集合总结

    集合是一些有共同特征的独立数据项组成的,通过集合,我们可以可以使用相同的调用代码来处理一个集合的所有元素,而不用单独处理每一个单独的项..net的集合诸如(System.Array类以及 System.Collections命名空间)数组.列表.队列.堆栈.哈希表.字典甚至(System.Data下)DataSet.DataTable,还有2.0中加入的集合的泛型版本(System.Collections.Generic和 System.Collections.ObjectModel),4.0中

  • asp.net php asp jsp 301重定向的代码(集合)

    1.Linux主机重定向 Godaddy的Liunx主机,Godaddy本身已经支持Apache,所以直接创建一个.htaccess文件就可以了,一般来说,在本地无法创建.htaccess的时候可以先创建一个txt格式文件,上传到根目录的时候再重命名为".htaccess"就可以了.网上很多如何进行 301重定向的教程,无论是整站重定向还是单页重定向.下面就以我的www.jb51.net为例 1.1 无www域名转移到www域名 复制代码 代码如下: RewriteEngine on

  • .Net中的集合排序可以这么玩你知道吗

    C#集合类型概述 集合是.NET FCL(Framework Class Library)中很重要的一部分.所有的集合类都继承自IEnumerable.集合类总体可分为一下几类:关联/非关联型集合,顺序/随机访问集合,顺序/无序集合,泛型/非泛型集合,线程安全集合. 各集合类底层接口关系图 背景: public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity) {

  • .Net集合排序的一种高级玩法实例教程

    前言 本文主要介绍了关于.Net集合排序的另一种高级玩法,文中通过示例代码介绍的非常详细,需要的朋友可以参考学习,下面话不多说了,来一起看看详细的介绍吧 背景: 学生有名称.学号, 班级有班级名称.班级序号 学校有学校名称.学校编号(序号) 需求  现在需要对学生进行排序 第一排序逻辑 按学校编号(序号)排列 再按班级序号排列 再按学生学号排列 当然,在我们录入数据库信息的时候,有的人可能比较懒,没有录入 学校的序号, 班级的序号,学生的学号 ,怎么办?  那么就Plan B  ! 第二排序逻辑

  • C# 中的List.Sort()--集合排序方法全面解析

    在C#中,List.Sort() 不仅为我们提供了默认的排序方法,还为我们提供了4种自定义排序的方法,通过默认排序方法,我们无需重写任何Sort()方法的实现代码,就能对单参数类型的List数据进行单一规则的排序,如果通过对这些方法进行改进我们可以轻松做到对多参数.多规则的复杂排序. 下面是C#自定义排序的4种方法: List<T>.Sort(); List<T>.Sort(IComparer<T> Comparer); List<T>.Sort(int i

  • Java中七种排序算法总结分析

    目录 前言:对文章出现的一些名词进行解释 一.插入排序 1.基本思想 2.直接插入排序 3.希尔排序(缩小增量排序) 二.选择排序 1.基本思想 2.直接选择排序 3.堆排序 三.交换排序 1.基本思想 2.冒泡排序 3.快速排序(递归与非递归) 1.Hoare版 2.挖坑法 3.前后标记法(难理解) 4.快速排序优化 5.快速排序非递归 6.相关特性总结 四.归并排序(递归与非递归) 前言:对文章出现的一些名词进行解释 排序: 使一串记录,按照其中的某个或某些关键字的大小,递增或者递减排列起来

  • C#中的集合用法分析

    本文实例讲述了C#中的集合用法,分享给大家供大家参考.具体分析如下: [集合不同于数组,是一组可变类型的.可变数量的元素的组合,这些元素可能共享某些特征,需要以某种操作方式一起进行操作.一般来讲,为了便于操作这些元素的类型是相同的] [集合与数组的区别:数组是连续的.同一类型数据的一块区域,而集合可以是不连续的,多种数据类型] [在集合中 foreach() 也是适用的] 1·集合的定义: 复制代码 代码如下: ArrayList al = new ArrayList();  //定义一个 集合

  • Java常用工具类—集合排序

    一.集合排序概述 1.主要内容 集合中的基本数据类型排序 集合中的字符串排序 Comparator接口 Comparable接口 回顾: //数组的排序 int[] arr= {2,3,4,5,2,1}; Arrays.sort(arr); 2.集合排序方法 使用Collections类的sort(List list)方法 sort(List list)是根据元素的自然顺序对指定列表按升序进行排序. 二.对基本数据类型和字符串类型进行排序 1.对基本数据类型排序 List中只能存放对象,要想存放

  • Java sort集合排序的两种方式解析

    这篇文章主要介绍了Java sort集合排序的两种方式解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Comparable和Comparator public static <T> void sort(List<T> list); 将集合中的数据按照默认规则进行排序 (我们在自己的类里面实现Comparabl接口方法compareTo) public static <T> void sort(List<T&g

  • Java List集合排序实现方法解析

    这篇文章主要介绍了Java List集合排序实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.使用 Collections 工具类中的 sort() 方法 参数不同: void sort(List list) 在自定义类User里面实现Comparable<User>接口,并重写抽象方法compareTo(Student o); void sort(List list, Comparator c) 第二个参数为了省事,可以直接使

  • java list集合排序按某一属性排序操作

    我就废话不多说了,大家还是直接看代码吧~ public List<FreightM> sortList(List<FreightM> list){ Collections.sort(list, new Comparator<FreightM>(){ @Override public int compare(FreightM o1, FreightM o2) { if(o1.getType()==0){ return -1; }else{ return 1; } } })

  • Java中List集合对象去重及按属性去重的8种方法

    最近在写一些关于java基础的文章,但是我又不想按照教科书的方式去写知识点的文章,因为意义不大.基础知识太多了,如何将这些知识归纳总结,总结出优缺点或者是使用场景才是对知识的升华.所以我更想把java相关的基础知识进行穿针引线,进行整体上的总结. 总结java中创建并写文件的5种方式 总结java从文件中读取数据的6种方法 总结java创建文件夹的4种方法及其优缺点 总结java中删除文件或文件夹的7种方法 总结java中文件拷贝剪切的5种方式 比如之前我已经写了上面的这些内容,如果对java基

随机推荐