改善C#程式的方法-3 比較器和LINQ排序

来源:https://www.cnblogs.com/wwwen/archive/2022/07/27/16524999.html
-Advertisement-
Play Games

一 創建對象時考慮實現比較器 假設有這樣的場景,有一個40個人的學生列表,業務中需針對學生的成績來進行排序。 可以考慮用IComparable介面和ICompare介面實現: class Program { static void Main(string[] args) { var stus = n ...


一 創建對象時考慮實現比較器

假設有這樣的場景,有一個40個人的學生列表,業務中需針對學生的成績來進行排序。

可以考慮用IComparable介面和ICompare介面實現:

class Program
{
    static void Main(string[] args)
    {
        var stus = new List<Student>();
        stus.Add(new Student() { Name = "zhangsan", EnglishGrades = 80.5, MathGrades = 90 });
        stus.Add(new Student() { Name = "lisi", EnglishGrades = 74, MathGrades = 91 });
        stus.Add(new Student() { Name = "wangwu", EnglishGrades = 94, MathGrades = 85.5 });
        stus.Add(new Student() { Name = "zhaoliu", EnglishGrades = 88.5, MathGrades = 86 });
      
        stus.Sort();
        Console.WriteLine("使用預設比較器排序:");
        foreach (var stu in stus)
        {
            Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
        }
        
        stus.Sort(new MathComparer());
        Console.WriteLine("使用自定義比較器排序:");
        foreach (var stu in stus)
        {
            Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
        }
        Console.ReadLine();
    }
}

//Student通過IComparable介面,實現預設比較器
class Student : IComparable<Student>
{
    public string Name { get; set; }

    public double EnglishGrades { get; set; }

    public double MathGrades { get; set; }

    public int CompareTo(Student stu)
    {
        if (EnglishGrades > stu.EnglishGrades)
        {
            return 1;
        }
        else if (EnglishGrades == stu.EnglishGrades)
        {
            return 0;
        }
        else
        {
            return -1;
        }
        //return EnglishGrades.CompareTo(stu.EnglishGrades); double類型的預設比較方法
    }
}

//通過IComparer介面實現自定義的比較器
class MathComparer : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        return x.MathGrades.CompareTo(y.MathGrades);
    }
}

輸出:

使用預設比較器排序:
Name:lisi,      English:74,     Math:91
Name:zhangsan,  English:80.5,   Math:90
Name:zhaoliu,   English:88.5,   Math:86
Name:wangwu,    English:94,     Math:85.5
使用自定義比較器排序:
Name:wangwu,    English:94,     Math:85.5
Name:zhaoliu,   English:88.5,   Math:86
Name:zhangsan,  English:80.5,   Math:90
Name:lisi,      English:74,     Math:91

 二 使用LINQ取代集合中的比較器

上述的方法實現的排序存在2個問題:

  • 可擴展性太低,如果存在新的排序要求,就必須實現新的比較器;
  • 對代碼的侵入性太高,為類型繼承了介面,新增了方法。

LINQ提供了類似於SQL的語法來實現遍歷、篩選和投影集合的強大功能,可以實現上述的排序要求。

static void Main(string[] args)
{
    var stus = new List<Student>();
    stus.Add(new Student() { Name = "zhangsan", EnglishGrades = 80.5, MathGrades = 90 });
    stus.Add(new Student() { Name = "lisi", EnglishGrades = 74, MathGrades = 91 });
    stus.Add(new Student() { Name = "wangwu", EnglishGrades = 94, MathGrades = 85.5 });
    stus.Add(new Student() { Name = "zhaoliu", EnglishGrades = 88.5, MathGrades = 86 });

    var orderByStus = from s in stus orderby s.EnglishGrades select s;
    //orderByStus = stus.OrderBy(s => s.EnglishGrades);
    foreach (var stu in orderByStus)
    {
        Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
    }
    Console.WriteLine();
    
    orderByStus = from s in stus orderby s.MathGrades select s;
    //orderByStus = stus.OrderBy(s => s.MathGrades);
    foreach (var stu in orderByStus)
    {
        Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
    }

    Console.ReadLine();
}

LINQ此功能的實現本身是藉助於FCL泛型集合的比較器、迭代器和索引器。LINQ封裝了這些功能,讓我們使用更加方便。

在命名空間System.Linq下的Enumerable方法中為泛型集合提供了很多擴展方法。

如排序中使用到的OrderBy方法:

   public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

它為繼承了IEnumerable<T>介面的集合提供排序的功能。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [數據結構-線性表1.1] 數組(.NET源碼學習) 數組,一種數據類型(在絕大數語言中不是基本數據類型)且為引用類型,在記憶體中以連續的記憶體單元進行分配,所以其大小在創建對象後為定值,不可更改。 一.記憶體分配 對於兩種不同數據類型而言,其記憶體分配方式是不同的。值類型直接在棧(C#中稱為堆棧Stack ...
  • 一 併發編程簡介 1.1 關於併發和並行 併發和並行的概念: 併發:(Concurrent),在某個時間段內,如果有多個任務執行,即有多個線程在操作時,如果系統只有一個CPU,則不能真正同時進行一個以上的線程, 它只能把CPU運行時間劃分成若幹個時間段,再將時間段分配給各個線程執行,在一個時間段的線 ...
  • 前言 接著上周寫的截圖控制項繼續更新 縮放操作。 1.WPF實現截屏「仿微信」 2.WPF 實現截屏控制項之移動(二)「仿微信」 正文 實現拉伸放大或縮小縮放操作需在矩形四個方向繪製8個Thumb,這裡有兩種方式 1)可以自行在XAML中硬編寫8個Thumb 2)使用裝飾器Adorner 本章使用了第二 ...
  • ASP.NET Web 應用 Docker踩坑歷程發表後,也開始使用Docker了,然而發佈的過程比較痛苦,經常發生下圖的事情: 據說是nuget包還原時發生錯誤 百度了半天也找不到解決的方法,而發生的概率有相當高,很是無語。 仔細看了自動生成的Dockerfile FROM mcr.microso ...
  • 今天在處理一個接收API通過Post方式傳送Json數據的方法時,碰到接收的Json數據一直是空的問題。最好找了好久才解決,現在把需要的問題列出來。 1. 在一般處理程式中,需要設置 context.Request.InputStream.Position = 0; 剛開始設置了這個,但後面還是為空 ...
  • 前言 如標題所述,在ASP.NET應用程式開發中,兩個集合做比較時 我們使用微軟IEnumerable封裝的 Except/Intersect/Union 取 差集/交集/並集 方法是非常的方便的; 但以上對於不太熟悉的小伙伴來講,在遇到求包含引用類型(不包含string)集合時就非常的苦惱; 下麵 ...
  • WPF的拖曳效果,基本配置一下,就可以了,但是自繪的話,就得自己控制,按鍵點擊,按鍵移動和按鍵鬆開的事件,與其配合達到目的。 ...
  • 1.前言 hi,大家好,我是三合。我是怎麼想起寫一篇關於資料庫快速批量插入的博客的呢?事情起源於我們工作中的一個需求,簡單來說,就是有一個定時任務,從資料庫里獲取大量數據,在應用層面經過處理後再把結果批量插入回到資料庫里。這個任務每十分鐘執行一次,但是有的時候數據量太大,迴圈插入資料庫的時候會超時, ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...