溫馨提示×

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

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

.Net集合排序的示例分析

發(fā)布時(shí)間:2021-08-05 14:35:07 來(lái)源:億速云 閱讀:123 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān).Net集合排序的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

背景:

學(xué)生有名稱、學(xué)號(hào),

班級(jí)有班級(jí)名稱、班級(jí)序號(hào)

學(xué)校有學(xué)校名稱、學(xué)校編號(hào)(序號(hào))

需求 

現(xiàn)在需要對(duì)學(xué)生進(jìn)行排序

第一排序邏輯

  • 按學(xué)校編號(hào)(序號(hào))排列

  • 再按班級(jí)序號(hào)排列

  • 再按學(xué)生學(xué)號(hào)排列

當(dāng)然,在我們錄入數(shù)據(jù)庫(kù)信息的時(shí)候,有的人可能比較懶,沒有錄入 學(xué)校的序號(hào), 班級(jí)的序號(hào),學(xué)生的學(xué)號(hào) ,怎么辦?  那么就Plan B  ! 

第二排序邏輯

  • 按學(xué)校名稱排列

  • 再按班級(jí)的名稱排列

  • 再按學(xué)生名稱排列

我編寫了學(xué)校、班級(jí)、學(xué)生的實(shí)體關(guān)系代碼如下: 

namespace Sort
{
 public class School
 {
 public int? Order { get; set; }
 public string Name { get; set; }
 }

 public class Class
 {
 public int? Order { get; set; }
 public string Name { get; set; }
 public School School { get; set; }
 }

 public class Student
 {
 public int? Order { get; set; }
 public string Name { get; set; }
 public Class Class { get; set; }

 }
}

以前寫的簡(jiǎn)單排序,還可以用OrderBy解決,如果之前寫過(guò)的一篇文章:

《.Net中集合排序還可以這么玩》

但是這里的排序就比較復(fù)雜了,用簡(jiǎn)單的OrderBy恐怕是解決不了了。

Sort

.Net中,對(duì)List集合,有一個(gè)Sort字方法,讓我們選中Sort方法,F(xiàn)12,看看Sort方法長(zhǎng)哪樣?

.Net集合排序的示例分析 

可以看到Sort方法一共有四個(gè)重載,我們挑最基礎(chǔ)的一個(gè),Sort()  0參數(shù)的這個(gè),懂了這個(gè),其他幾個(gè)應(yīng)該也會(huì)懂了,我們看看該方法的描述:

.Net集合排序的示例分析 

雖然我英語(yǔ)不太好,但是這基礎(chǔ)的英語(yǔ)還是能看懂,大致是說(shuō):

用默認(rèn)的比較器對(duì)該List進(jìn)行排序。

那么,這個(gè)Comparer(比較器)是什么呢?

IComparable接口

其實(shí),它是接口IComparable下的一個(gè)方法,也就是說(shuō)只有實(shí)現(xiàn)了ICoparable接口下的這個(gè)叫比較器的方法才能使用Sort進(jìn)行排序,我們F12進(jìn)入到IComparable來(lái)看看這個(gè)接口:

.Net集合排序的示例分析 

可以看到,該接口只有一個(gè)CompareTo方法,我用我蹩腳的英語(yǔ)大致看懂了這句話的意思是:

定義一個(gè)比較方法來(lái)對(duì)制定類型進(jìn)行排序。

該方法返回類型為Int類型。通過(guò)查找查找相關(guān)資料,了解到其返回值與其含義如下:

含義

復(fù)數(shù)

該實(shí)例比傳入的Other實(shí)例小。

0

該實(shí)例與傳入的Other實(shí)例相等。

正數(shù)

該實(shí)例比傳入的Other實(shí)例大。

知道了這個(gè)原則,我們就可以給Student類繼承并實(shí)現(xiàn)該方法了。

對(duì)文章開頭的排序需求,我們重溫一下:

第一排序邏輯(Int?)

  • 按學(xué)校編號(hào)(序號(hào))排列

  • 再按班級(jí)序號(hào)排列

  • 再按學(xué)生學(xué)號(hào)排列

當(dāng)序號(hào)為空時(shí),用第二種排序邏輯,

第二排序邏輯(String)

  • 按學(xué)校名稱排列

  • 再按班級(jí)的名稱排列

  • 再按學(xué)生名稱排列

其實(shí)無(wú)非就是對(duì)Student中涉及到的Int?和string兩種數(shù)據(jù)類型進(jìn)行比較。

Int?類型(Nullable)和string已經(jīng)實(shí)現(xiàn)了Compare方法,其中Nullable的如下:

但是為了能更深入地理解該方法的使用,我自己來(lái)寫一個(gè)Int?類型數(shù)據(jù)比較的方法,如下:

private int CompareInit(int? x, int? y)
 {
  if (x == null && y == null) //如果都是空 那么返回0相等
  return 0;

  if (x.HasValue && y == null) //如果傳入X有值,但是Y是空的,那么X比Y小 返回-1。
  return -1;

  if (x == null && y.HasValue) //如果傳入X為空,但是Y有值,那么X比Y大 返回1。
  return 1;

  if (x.Value > y.Value)
  return 1;

  if (x.Value < y.Value)
  return -1;

  return 0;   //否則兩個(gè)數(shù)相等
 }

其中,為什么我認(rèn)為有值的比Null的還小返回-1呢? 因?yàn)槲蚁氚袾ull的往后排,把有值的往前排,其他流行的做法是認(rèn)為有值的是比Null大的,即返回1,大家可以結(jié)合自己的業(yè)務(wù)需求選擇。

寫好了Int?類型數(shù)據(jù)比較的方法,還有String類型數(shù)據(jù)的比較,我就不自己造輪子去寫了,用現(xiàn)成的String.CompareOrdinal()方法。

然后,我們開始給Student實(shí)現(xiàn)ICompare接口的CompareTo方法,如下:

public class Student : IComparable<Student>
 {
  public int? Order { get; set; }
  public string Name { get; set; }
  public Class Class { get; set; }
  public int CompareTo(Student other)
  {
   if (ReferenceEquals(this, other)) return 0; //如果兩個(gè)值的引用相同,那么直接返回相等。
   if (ReferenceEquals(null, other)) return 1; //如果該實(shí)例是空的,但是傳入的實(shí)例不是空的,那么返回1
   //比較學(xué)校的序號(hào)
   var compareResult = CompareInit(this.Class.School.Order, other.Class.School.Order);
   if (compareResult != 0) return compareResult;
   //比較班級(jí)的序號(hào)
   compareResult = CompareInit(this.Class.Order, other.Class.Order);
   if (compareResult != 0) return compareResult;
   //比較學(xué)生的學(xué)號(hào)
   compareResult = CompareInit(this.Order, other.Order);
   if (compareResult != 0) return compareResult;
   //如果以上還未區(qū)分出大小,比較學(xué)校的名稱
   compareResult = String.CompareOrdinal(this.Class.School.Name, other.Class.School.Name);
   if (compareResult != 0) return compareResult;
   //比較班級(jí)的名稱
   compareResult = String.CompareOrdinal(this.Class.Name, other.Class.Name);
   if (compareResult != 0) return compareResult;
   //比較學(xué)生的名稱
   return String.CompareOrdinal(this.Name, other.Name);

  }

實(shí)現(xiàn)該方法后,就可以對(duì)List<Student> 使用Sort方法了,我們來(lái)試試看。

using System;
using System.Collections.Generic;

namespace Sort
{
 class Program
 {
  static void Main(string[] args)
  {
   var students = InitData();
   students.Sort(); //此處執(zhí)行了Sort方法
   Console.WriteLine("Name-Order");
   foreach (var student in students)
   {
    Console.WriteLine($"學(xué)校:{student.Class.School.Name}-{student.Class.School.Order}>>班級(jí):{student.Class.Name}-{student.Class.Order}>>學(xué)生:{student.Name}-{student.Order}");
   }

   Console.ReadLine();
  }

  static List<Student> InitData() //創(chuàng)建數(shù)據(jù)
  {
   var school1 = new School()
   {
    Order = 1,
    Name = "A",

   };
   var school2 = new School
   {
    Name = "B",
    Order = 0
   };

   var class1 = new Class
   {
    Order = 1,
    Name = "1",
    School = school1,
   };

   var class2 = new Class
   {
    Order = 2,
    Name = "2",
    School = school1,
   };

   var class3 = new Class
   {
    Order = 1,
    Name = "1",
    School = school2,
   };

   var student1 = new Student
   {
    Order = 1,
    Name = "1",
    Class = class1,
   };

   var student2 = new Student
   {
    Order = 2,
    Name = "2",
    Class = class1,
   };

   var student3 = new Student
   {
    Order = 3,
    Name = "3",
    Class = class1,
   };

   var student4 = new Student
   {
    Order = 1,
    Name = "1",
    Class = class2,
   };

   var student5 = new Student
   {
    Order = 1,
    Name = "1",
    Class = class3,
   };
   return new List<Student> { student5, student3, student4, student2, student1 };

  }
 }
}

執(zhí)行效果如下:

.Net集合排序的示例分析 

可以看到,學(xué)校B雖然是以B開頭,但是因?yàn)槠贠rder為0比1更靠前,所以以O(shè)rder為準(zhǔn),學(xué)校B排到了最前面。

感謝各位的閱讀!關(guān)于“.Net集合排序的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向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