91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在C# 中利用List.Sort()方法對集合進行排序

發布時間:2021-01-15 15:05:50 來源:億速云 閱讀:314 作者:Leah 欄目:開發技術

怎么在C# 中利用List.Sort()方法對集合進行排序?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

在C#中,List.Sort() 不僅為我們提供了默認的排序方法,還為我們提供了4種自定義排序的方法,通過默認排序方法,我們無需重寫任何Sort()方法的實現代碼,就能對單參數類型的List數據進行單一規則的排序,如果通過對這些方法進行改進我們可以輕松做到對多參數、多規則的復雜排序。

下面是C#自定義排序的4種方法:

List<T>.Sort();     
List<T>.Sort(IComparer<T> Comparer);
List<T>.Sort(int index, int count, IComparer<T> Comparer);
List<T>.Sort(Comparison<T> comparison);

實現目標

假設存在一個People類,包含Name、Age屬性,在客戶端中創建List保存多個實例,希望對List中的內容根據Name和Age參數進行排序,排序規則為,先按姓名升序排序,如果姓名相同再按年齡的升序排序:

class People
{
  public People(string name, int age) { Name = name; Age = age; }
  public string Name { get; set; } //姓名
  public int Age { get; set; } //年齡
}
 
// 客戶端
class Client
{
  static void Main(string[] args)
  {
    List<People> peopleList = new List<People>();
    peopleList.Add(new People("張三", 22));
    peopleList.Add(new People("張三", 24));
    peopleList.Add(new People("李四", 18));
    peopleList.Add(new People("王五", 16));
    peopleList.Add(new People("王五", 30));
  }
}

方法一、對People類繼承IComparable接口,實現CompareTo()方法

該方法為系統默認的方法,單一參數時會默認進行升序排序。但遇到多參數(Name、Age)排序時,我們需要對該默認方法進行修改。

方法一:People類繼承IComparable接口,實現CompareTo()方法

IComparable<T>:定義由值類型或類實現的通用比較方法,旨在創建特定于類型的比較方法以對實例進行排序。

原理:自行實現的CompareTo()方法會在list.Sort()內部進行元素兩兩比較,最終實現排序

class People : IComparable<People>
{
  public People(string name, int age) { Name = name;Age = age; }
  public string Name { get; set; }
  public int Age { get; set; }
 
  // list.Sort()時會根據該CompareTo()進行自定義比較
  public int CompareTo(People other)
  {
    if (this.Name != other.Name)
    {
      return this.Name.CompareTo(other.Name);
    }
    else if (this.Age != other.Age)
    {
      return this.Age.CompareTo(other.Age);
    }
    else return 0;
  }
}
 
// 客戶端
peopleList.Sort();
 
// OUTPUT:
//   李四 18
//   王五 16
//   王五 30
//   張三 22
//   張三 24

方法二:增加People類的外部比較類,繼承IComparer接口、實現Compare()方法

區別于上述繼承IComparable的方法,該方法不可在People內繼承實現IComparer接口,而是需要新建比較方法類進行接口實現

方法二:新建PeopleComparer類、繼承IComparer接口、實現Compare()方法

原理:list.Sort()將PeopleComparer類的實例作為參數,在內部使用Compare()方法進行兩兩比較,最終實現排序(注:上述方法為CompareTo(),此處為Compare()方法)

// 自定義比較方法類
class PeopleComparer : IComparer<People>
{
  // 區別于CompareTo()單參數,此處為雙參數
  public int Compare(People x, People y)
  {
    if (x.Name != y.Name)
    {
      return x.Name.CompareTo(y.Name);
    }
    else if (x.Age != y.Age)
    {
      return x.Age.CompareTo(y.Age);
    }
    else return 0;
  }
}
 
// 客戶端
// 傳入參數為自定義比較類的實例      
peopleList.Sort(new PeopleComparer());
 
// OUTPUT:
//   李四 18
//   王五 16
//   王五 30
//   張三 22
//   張三 24

同理,List<T>.Sort(int index, int count, IComparer<T> Comparer) 方法的參數:待排元素起始索引、待排元素個數、排序方法

方法三、采用泛型委托 Comparison<T>,綁定自定義的比較方法

區別于上述繼承接口的方法,此方法的參數為 泛型委托 Comparison<T>

委托原型:public delegate int Comparison<in T>(T x, T y);

方法三:依照委托的使用方法,首先創建委托實例MyComparison,并綁定到自定義的比較方法PeopleComparison()上,最終調用list.Sort()時 將委托實例傳入

原理:list.Sort()根據傳入的委托方法,進行兩兩元素比較最終實現排序

// 客戶端
class Client
{
  // 方法0 自定義比較方法
  public static int PeopleComparison(People p1, People p2)
  {
    if (p1.Name != p2.Name)
    {
      return p1.Name.CompareTo(p2.Name);
    }
    else if (p1.Age != p2.Age)
    {
      return p1.Age.CompareTo(p2.Age);
    }
    else return 0;
  }
 
  static void Main(string[] args)
  {
    / 創建list ... /
    
    // 方法0 創建委托實例并綁定
    Comparison<People> MyComparison = PeopleComparison;
 
    // 傳入該實例實現比較方法
    peopleList.Sort(MyComparison);
 
    // OUTPUT:
    //   李四 18
    //   王五 16
    //   王五 30
    //   張三 22
    //   張三 24
  }
}

此外,既然Comparison<T>是泛型委托,則完全可以用 Lambda表達式 進行描述:

// Lambda表達式實現Comparison委托
peopleList.Sort((p1, p2) =>
{
  if (p1.Name != p2.Name)
  {
    return p2.Name.CompareTo(p1.Name);
  }
  else if (p1.Age != p2.Age)
  {
    return p2.Age.CompareTo(p1.Age);
  }
  else return 0;
});
 
// OUTPUT:
//   張三 24
//   張三 22
//   王五 30
//   王五 16
//   李四 18

總結

雖然本文僅使用了List<T>一種容器對Sort()方法進行闡述,但是不同容器的使用Sort()的方法大相徑庭,因為核心的原理都是應用兩種接口及泛型委托:

兩種接口:IComparable<T> 、 IComparer<T>

泛型委托:Comparison<T>

參考

IComparable接口 - Microsoft

Comparison委托 - Microsoft

IComparer接口 - Microsoft

附:一個完整的測試Demo

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 
namespace ListSort
{
  class Program
  {
    static void DisplayInfo<T>(List<T> list) {
      //輸出List元素內容
      foreach(var item in list) {
        System.Console.Write("{0} ",item.ToString());
      }
      System.Console.WriteLine("");
    }
 
    // 方法3 自定義委托泛型比較方法
    public static int PeopleComparison(People p1, People p2)
    {
      if (p1.Name != p2.Name)
      {
        return p1.Name.CompareTo(p2.Name);
      }
      else if (p1.Age != p2.Age)
      {
        return p1.Age.CompareTo(p2.Age);
      }
      else return 0;
    }
    static void Main(string[] args)
    {
      List<People> peopleList = new List<People>();
      peopleList.Add(new People("張三", 22));
      peopleList.Add(new People("張三", 24));
      peopleList.Add(new People("李四", 18));
      peopleList.Add(new People("王五", 16));
      peopleList.Add(new People("王五", 30));
 
      System.Console.WriteLine("排序前原始數據:");
      DisplayInfo(peopleList);
      System.Console.WriteLine("------------------------------------");
 
      System.Console.WriteLine("方法1排序后數據:");
      peopleList.Sort();
      DisplayInfo(peopleList);
 
      System.Console.WriteLine("方法2排序后數據:");
      DisplayInfo(peopleList);
 
      // 方法1 使用IComparer<T>接口。
      peopleList.Sort(new PeopleComparer());
 
      // 方法2 除以上兩種方法以外還可以使用另一種方法,在People類中實現IComparable<T>
      peopleList.Sort();
      System.Console.WriteLine("方法3排序后數據:");
      DisplayInfo(peopleList);
 
      // 方法3 創建泛型委托實例并綁定
      Comparison<People> MyComparison = PeopleComparison;
 
      // 傳入該實例實現比較方法
      peopleList.Sort(MyComparison);
 
      System.Console.WriteLine("方法3排序后數據:");
      DisplayInfo(peopleList);
 
      // 方法3 使用Comparison<T>委托,Lambda寫法
      peopleList.Sort((left, right) =>
      {
        //先按姓名排序,如果姓名相同再按年齡排序
        int x = left.Name.CompareTo(right.Name);
        if(x==0) {
          if (left.Age > right.Age)
            x = 1;
          else if (left.Age == right.Age)
            x = 0;
          else
            x = -1;
        }
        return x;
      }); 
    }
  }
 
  //方法一
  public class People : IComparable<People>
  {
    public int Age { get;set;}
    public string Name { get;set;}
    public People(string name,int age) {
      this.Name = name;
      this.Age = age;
    }
 
    public override string ToString() {
      string result = "";
      result = "["+this.Name+","+ this.Age.ToString()+"]";
      return result; 
    }
 
    public int CompareTo(People other)
    {
      int x = this.Name.CompareTo(other.Name);
      if(x==0) {
        if (this.Age > other.Age)
          x = 1;
        else if (this.Age == other.Age)
          x = 0;
        else
          x = -1;
      }
      return x;
    }
  }
 
  //方法二
  public class PeopleComparer : IComparer<People>
  {
    public int Compare(People left, People right)
    {
      int x = left.Name.CompareTo(right.Name);
      if(x==0) {
        if (left.Age > right.Age)
          x = 1;
        else if (left.Age == right.Age)
          x = 0;
        else
          x = -1;
      }
      return x;
    }
  } 
}

補充:C# IComparable和IComparer接口和自定義比較器

前言

ArrayList里面有一個方法:

public virtual void Sort(IComparer comparer);

使用指定的比較器對整個 System.Collections.ArrayList 中的元素進行排序。

comparer:比較元素時要使用的 System.Collections.IComparer 實現。

啥玩意啊?

正文

1.Comparer類簡單介紹

想弄清楚這個,我們先來看看這么一個類。

在System.Collections名稱空間中,有這么一個類:Comparer。顧名思義,他可以實現對簡單類型的比較,什么意思呢?來看如下代碼:

int a=1,b=2;

正常情況下,我們要怎樣比較他們的大小?if,運算符,……?這當然可以,不過Comparer已經給我們提供了一個函數,可以直接使用:(需要using System.Collections;)

Console.WriteLine(Comparer.Default.Compare(a,b));

因為a<b,所以控制臺會輸出-1。(這個函數總是返回-1,0,1三個值。)

這里通過Comparer里的靜態屬性Default獲得Comparer的實例調用了Comparer里的非靜態函數Compare。

(還可以比較根據字母比較兩個string類型,這里就省略介紹了)

2.自定義比較器,IComparable,IComparer接口

當然,這個類不僅僅只是用來比較兩個數的大小的。有時候我們想直接比較兩個對象,但是引用里面的屬性或許比較麻煩。尤其是參考要素過多,不好直接比較的時候,怎樣才能更高效地比較兩個對象呢?這時候,我們就需要自定義比較器了。

首先來介紹IComparable接口。這個接口里只有一個方法CompareTo()。讓你的類實現這個接口的CompareTo方法,就可以直接調用這個方法和另一個對象比較。下面是例子:

public class ClassTest : IComparable
{
 public int intTest;
 public int CompareTo(object obj)
 {
  return intTest-((ClassTest)obj).intTest;
  //這里的代碼可以按需要自己編寫,這里只是一個簡單的示例
 }
}

然后就可以直接使用啦:

ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
Console.WriteLine(a.CompareTo(b));//輸出-1
Comparer類已經為我們提供了IComparer的默認實現,但我們仍然可以自定義它。新建一個類:(記得using System.Collections;)
public class ClassTestComparer : IComparer
{
 public static IComparer Default = new ClassTestComparer();
 //這里必須使用這樣的定義,將對象轉化為IComparer類型有很大用處,下面會介紹
 public int Compare(object a,object b)
 {
  return ((ClassTest)a).intTest - ((ClassTest)b).intTest;
  //同樣這里使用最簡單的示例,但是你可以大放異彩
 }
}

注意,如果用于比較的類和設定的類不一樣,就會出現錯誤。

使用示例:

ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
Console.WriteLine(ClassTestComparer.Default.Compare(a,b));
//結果是-1

可以發現,這兩個接口的不同之處在于:IComparable在要比較的對象的類中實現,可以比較該對象和另一個對象。IComparer在一個單獨的類中實現,可以比較任意兩個對象(關鍵是你的設置)。

3.對集合排序

當然,這兩個接口還有更強大的用處。我們可以使用這兩個接口對集合進行排序。還記得前言里的Sort()方法嗎?接下來就以ArrayList為例,介紹如何使用。

ArrayList ClassTests = new ArrayList();
ClassTest a = new ClassTest(){intTest=1};
ClassTest b = new ClassTest(){intTest=2};
ClassTest c = new ClassTest(){intTest=3};
ClassTests.Add(a);
ClassTests.Add(b);
ClassTests.Add(c);
ClassTests.Sort();
//使用無參的Sort,將調用類中的CompareTo()方法,因為ClassTest實現了這個方法,所以是可以調用的。如果沒有實現,編譯器會報錯。
ClassTests.Sort(ClassTestComparer.Default);
//這將使用Compare()方法對集合中的元素排序。ClassTestComparer類實現了這個方法,并且提供了一個IComparer類型的屬性。

需要注意的是:

兩個接口提供的方法返回值都是int類型的,負數代表小于,0代表等于,正數代表大于。所以對數字之外的自定義比較器,需要人工設定什么是“大”,什么是“小”。所以上文示例中兩個數直接相減,就可以比較大小。

排序完之后,按照返回的int值,集合是由小到大排列的。

使用無參Sort()時,集合中至少要有一個類實現了IComparable,否則會報錯。

一般來說,都是對同一個類進行比較。不過,也可以實現對不同類比較的代碼,這就看具體需要了。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鱼台县| 南雄市| 陇川县| 瑞丽市| 英吉沙县| 涿鹿县| 高尔夫| 普宁市| 鄱阳县| 方正县| 朝阳市| 靖边县| 鲁山县| 涪陵区| 彭阳县| 泊头市| 兴国县| 南乐县| 武平县| 长沙县| 射洪县| 会宁县| 勃利县| 抚远县| 龙游县| 静海县| 城步| 禄丰县| 绥江县| 嵩明县| 吉水县| 绥滨县| 二手房| 内江市| 都昌县| 西吉县| 宜春市| 甘德县| 青阳县| 措美县| 精河县|