溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

.Net中怎么實(shí)現(xiàn)集合排序

發(fā)布時(shí)間:2021-08-12 15:07:07 來(lái)源:億速云 閱讀:207 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

.Net中怎么實(shí)現(xiàn)集合排序,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

C#集合類型概述

集合是.NET FCL(Framework Class Library)中很重要的一部分。所有的集合類都繼承自IEnumerable。集合類總體可分為一下幾類:關(guān)聯(lián)/非關(guān)聯(lián)型集合,順序/隨機(jī)訪問(wèn)集合,順序/無(wú)序集合,泛型/非泛型集合,線程安全集合。

各集合類底層接口關(guān)系圖

.Net中怎么實(shí)現(xiàn)集合排序

背景:

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

該對(duì)象,主要有三個(gè)字段,現(xiàn)在的業(yè)務(wù)需求是,取到了一個(gè)類型為L(zhǎng)ist<StockQuantity>集合StockQuantities,需要對(duì)該集合進(jìn)行三次排序,排序規(guī)則及優(yōu)先級(jí)如下:

1.    Status為空的排在后面,不為空的排在前面,不關(guān)心Status的內(nèi)容,只關(guān)心Status是否為空。

2.    DateTime升序排序。

3.    Quantity升序排序。

小白我的做法:

我只知道可以對(duì)集合用OderBy排序,對(duì)以上三條規(guī)則,所以設(shè)計(jì)思路如下。

1.    StockQuantities.OrderBy(u=>u.Status)

錯(cuò)誤,

該排序得規(guī)則不僅僅會(huì)考慮Status是否為空,還會(huì)考慮Status的內(nèi)容。

如果Status是[“b”,”c”,null,”d”] ,那么排序結(jié)果是[null,“b”,”c”,”d”] 。

而我們要的結(jié)果是[“b”,”c”,”d” ,null]  (直接把null的丟到最后,別的不動(dòng))

怎么辦?

暫時(shí)不知道,先不管

2.    對(duì)DateTime進(jìn)行升序排序,這簡(jiǎn)單

StockQuantities.OrderBy(u=>u.DateTime)

半對(duì)!

為什么半對(duì),看下面

3.    在排序2的前提下,用OrderBy,也就是StockQuantities.OrderBy(u=>u.DateTime).OrderBy(u=>u.Quantity)

錯(cuò)誤!

以上表達(dá)式等同于下面兩條的表達(dá)式:

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

所以第一條代碼就是廢代碼,最終排序還是以Quantity進(jìn)行排序的。

雖然我是小白,但我還是明白這樣是錯(cuò)誤的,所以我的做法是

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

采用雙層循環(huán),先取到按時(shí)間排序的數(shù)據(jù) dateOrder,再去和該條數(shù)據(jù)在同一天的所有數(shù)據(jù)并對(duì)Quantity進(jìn)行排序,為了防止重復(fù)的輸出,我同時(shí)給StockQuantity對(duì)象加上了Output屬性,當(dāng)該屬性為false為,則輸出該對(duì)象的內(nèi)容,并把Output屬性設(shè)為true,這樣就不會(huì)重復(fù)輸出了,而且實(shí)現(xiàn)了先對(duì)DateTime排序,再對(duì)Quantity進(jìn)行排序。
So Easy??!

然而,當(dāng)開(kāi)心地把這樣的代碼提交之后,卻被同事狠狠地鄙視了,說(shuō)到:“什么爛代碼?。 比坏肋€有比這更好的代碼?

給同事倒了一杯茶,點(diǎn)了一根煙,虛心請(qǐng)教。

大佬做法:

同事給我講了兩招,分別是條件排序、多級(jí)排序。

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

1.    StockQuantities.OrderBy(u=>u.Status==null)

這就是條件排序,可是咋一看,給人一種是把Status為空的排前面,不為空的排后面的錯(cuò)覺(jué)。

其實(shí)不然,我們看到OrderBy里面的一個(gè)返回值為bool類型的表達(dá)式,該排序先排結(jié)果為0(false)的,再排結(jié)果為1(true)的。這種排序只考慮返回的bool值,不考慮參數(shù)的具體值,所以姑且稱它為條件排序。

完全符合排序規(guī)則1的要求。

什么是多級(jí)排序,怎么用?

2.    利用我上面我的代碼排序雖然可以實(shí)現(xiàn)先排DateTime,再排Quantity,但是該算法的時(shí)間復(fù)雜度的n*n,而且給StockQuantity添加了output字段,明顯是不科學(xué)的。

然而,連續(xù)地使用多個(gè)OrderBy最終只會(huì)生效最后一個(gè)OrderBy,天無(wú)絕人之路,所以這個(gè)時(shí)候應(yīng)該使用ThenBy!!
使用ThenBy可以講以上的三條排序規(guī)則簡(jiǎn)化如下:

stockQuantities = stockQuantities.OrderBy(u => u.Status==null).ThenBy(u => u.DateTime).ThenBy(u => u.Quantity).ToList();

即可完美地實(shí)現(xiàn)再前一個(gè)排序前提下進(jìn)行二級(jí)排序。

優(yōu)化后的完整代碼如下:

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èi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI