JavaScript排序 — sort()方法(解決null、undefined、0之間的排序(混亂)問題)

来源:https://www.cnblogs.com/gby-web/archive/2022/09/30/16743564.html
-Advertisement-
Play Games

JavaScript排序 — sort()方法 ——解決null、undefined、0之間的排序(混亂)問題 一、普通的數組排序 ​ JavaScript中用方法sort()為數組排序。sort()方法有一個可選參數,是用來確定元素順序的函數。如果這個參數被省略,那麼數組中的元素將按照ASCII字 ...


此博客主要介紹JavaScript中sort()排序的使用方法,也進一步講述了:當排序的值存在null、undefined、0這三個特殊值時,解決排序混亂的方法,並結合自己的理解來闡述解決方法的原理。

JavaScript排序 — sort()方法

——解決null、undefined、0之間的排序(混亂)問題

一、普通的數組排序

​ JavaScript中用方法sort()為數組排序。sort()方法有一個可選參數,是用來確定元素順序的函數。如果這個參數被省略,那麼數組中的元素將按照ASCII字元順序進行排序。

  • 數組元素是字元串
//定義新字元串元素數組
var arr = ["a", "b", "A", "B"];
//sort()方法排序
arr.sort();
console.log(arr);//["A", "B", "a", "b"]

備註:因為字母AB的ASCII值分別為6566,而ab的值分別為9798,所以上面輸出的結果是 ["A", "B", "a", "b"]

  • 數組元素是數字
//定義新數字元素數組
var arr = [15, 8, 25, 3];
//sort()方法排序
arr.sort();
console.log(arr);//[15, 25, 3, 8]

​ 結果並不是我們想要的順序(理想順序:按數字大小排序)!原因如下:

​ sort()方法會對數組的每一項執行toString()方法,然後再對得到的字元串進行排序。所以之所以25比3大,但卻排在3之前,是因為比較的是字元串25和字元串3。如果要得到我們理想的數據,則使用比較函數(通俗的說就是sort()方法內的參數)

  • 比較函數的使用
//定義新數字元素數組
var arr = [15, 8, 25, 3];
//sort()方法排序
arr.sort((a,b)=>{
    //對數組進行遍歷,通過比較a與b的差值大小,來排序
    return a-b;
});
console.log(arr);//[3, 8, 15, 25]

二、數組對象排序

​ 其實和上文基本一致,只不過比較對象加了屬性值

//定義數組對象
var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":7,name:'pl'}]
//sort()方法排序
arr.sort((a,b)=>{
    //對數組進行遍歷,
    //通過對a對象的age屬性與b對象的age屬性
    //進行取差,根據插值大小,進而排序
    console.log(a['age']-b['age']);//-14 7 -17 7
    return a['age']-b['age'];
});
console.log(arr);//[{age: 0, name: 'ls'},{age: 7, name: 'pl'},{age: 24, name: 'zs'}]

​ 對比較函數進行提取:

//定義數組對象
var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":7,name:'pl'}]
//將比較方法進行提取
var compare = function (obj1, obj2) {
    var val1 = obj1.age;
    var val2 = obj2.age;
    return val1 - val2;        
} 
//[{age: 0, name: 'ls'},{age: 7, name: 'pl'},{age: 24, name: 'zs'}]
console.log(arr.sort(compare));

​ 對比較函數再進行改造,使得參數的輸入更加靈活!

var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":7,name:'pl'}]
var compare = function (prop) {
    return function (obj1, obj2) {
        var val1 = obj1[prop];
        var val2 = obj2[prop];
        return val1 - val2         
    } 
}
//[{age: 0, name: 'ls'},{age: 7, name: 'pl'},{age: 24, name: 'zs'}]
console.log(arr.sort(compare("age")));

重點:如果數組內某一對象為空值,排序是怎樣的呢?(顯然並不是按年齡順序排序的,因為存在nullundefined)

var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":0,name:'gr'},
         {"age":null,name:'yo'},{"age":7,name:'pl'},{"age":undefined,name:'tt'},
         {"age":null,name:'jz'},{"age":0,name:'mn'},{"age":undefined,name:'we'}]

//[{"age": 0,"name": "ls"},{"age": 0,"name": "gr"},{"age": null,"name": "yo"},
//{"age": null,"name": "jz"},{"age": 0,"name": "mn"},{"age": 7,"name": "pl"},
//{"age": 24,"name": "zs"},{"age":undefined,"name": "tt"},
//{"age":undefined,"name": "we"}]
console.log(arr.sort(compare("age")));

​ 我們可以知道上述比較函數是對比兩個值的插值(可以是數字的插值,也可以是ASCII的插值),同時我們又知道:當值為nullundefined0時,這三者任意方式搭配相減,其結果都為0!,並且使用if判斷都為false

解決辦法:可以製造特殊值之間與特殊值與正常值之間的差足夠大!

理解:

  • undefined - 所有值 = -9999 (也就是說undefined與其他值差的最多,排最小)
  • null - 所有值 = -999 (也就是說undefined與其他值差的第二多,排最第二小)
  • undefined - undefined = 0
  • null - null = 0
  • undefined - null = 0
  • 上述說明是等式a - b 那麼相反b - a規則也適用;也就是下文第二個if的返回值999 9999
  • -999和-9999、999,9999是用來區別其他差值的,也可根據實際情況進行差值設定
var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":0,name:'gr'},
         {"age":null,name:'yo'},{"age":7,name:'pl'},{"age":undefined,name:'tt'},
         {"age":null,name:'jz'},{"age":0,name:'mn'},{"age":undefined,name:'we'}]
var compare = function (prop) {
    return function (obj1, obj2) {
        var val1 = obj1[prop];
        var val2 = obj2[prop];
        if(!val1 && val1 != 0 && val2){
            //定義undefined特殊值的差值
	        if(val1 === undefined) return -9999
            //定義null特殊值的差值
	        return -999
	    }
	    if(!val2 && val2!= 0 && val1){
	        if(val2 === undefined) return 9999
	        return 999
	    }
	    return val1 - val2      
    } 
}
//[{age: undefined, name: 'we'},{age: undefined, name: 'tt'},{age: null, name: 'jz'},
//{age: null, name: 'yo'},{age: 0, name: 'ls'},{age: 0, name: 'gr'},
//{age: 0, name:'mn'},{age: 7, name: 'pl'},{age: 24, name: 'zs'}]
console.log(arr.sort(compare("age")));

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

-Advertisement-
Play Games
更多相關文章
  • 我嘗試了Debian,Ubuntu,Kali Linux都不能啟動Windows。每次裝完,磁碟格式都會自動變成MBR。結果今天嘗試了安裝Fedora 36,居然輕輕鬆松就成功了。。。 ...
  • 一、原理總結 利用兩個寄存器R4和R5來存儲兩個數位管的顯示效果,R4是前一個數位管顯示所需,而R5是後一個數位管顯示所需,利用左移操作RLC來使之每一位被依次輸入到C中,然後將C輸入到LED中(當LED每位都有數據時,數位管才會顯示),利用停頓函數使數位管上數字停留一段時間。 二、程式分析 以下為 ...
  • 前文回顧 實現一個簡單的Database1(譯文) 實現一個簡單的Database2(譯文) 實現一個簡單的Database3(譯文) 譯註:cstsck在github維護了一個簡單的、類似sqlite的資料庫實現,通過這個簡單的項目,可以很好的理解資料庫是如何運行的。本文是第三篇,主要是實現資料庫 ...
  • SELECT定義: SQL的SELECT語句可以實現對錶的選擇、投影及連接操作。即SELECT語句可以從一個或多個表中根據用戶的需要從資料庫中選出匹配的行和列,結果通常是生成一個臨時表。 SELECT語句功能強大,有很多子句,所有被使用的子句必須按語法說明的順序嚴格地排序。 查詢數據表,區分單列查詢 ...
  • 可能就會有人在問:安裝MySQL為什麼還要圖形化軟體? 實際上MySQL有兩種方式來執行請求,一是通過手打命令的方式,二是通過圖形化界面來進行操作,後者本質上也是通過輸入命令來執行請求,但是它可以使操作更簡單,避免一些重覆性的輸入。 這裡我將提供兩種流行的圖形化軟體:Navicat和DataGrip ...
  • Android許可權詢問 AndroidMaifest.xml中聲明許可權 <!-- 聲明所有需要的許可權(包括普通許可權和危險許可權) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses- ...
  • vue組件中最常見的數據傳遞就是父子組件之間的傳遞,父組件可以通過 props 向下傳數據給子組件,子組件可以通過 $emit 事件攜帶數據給父組件。然而當兩個頁面沒有任關係,該如何通信?這就引出了 EventBus ( 事件匯流排 ) 這個概念 初始化 方法一:新建文件 首先需要初始化一個 Even ...
  • #背景 什麼是tapable、hook,平時做vue開發時的webpack 配置一直都沒弄懂,你也有這種情況嗎? 還是看源碼,閑來無聊又看一下webpack的源碼,看看能否找到一些寶藏 tapable和webpack沒有特定關係,可以先看下這篇文章,瞭解下這個小型庫 https://webpack. ...
一周排行
    -Advertisement-
    Play Games
  • 在C#中使用SQL Server實現事務的ACID(原子性、一致性、隔離性、持久性)屬性和使用資料庫鎖(悲觀鎖和樂觀鎖)時,你可以通過ADO.NET的SqlConnection和SqlTransaction類來實現。下麵是一些示例和概念說明。 實現ACID事務 ACID屬性是事務處理的四個基本特征, ...
  • 我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下... ...
  • 在本篇教程中,我們學習瞭如何在 Taurus.MVC WebMVC 中進行數據綁定操作。我們還學習瞭如何使用 ${屬性名稱} CMS 語法來綁定頁面上的元素與 Model 中的屬性。通過這些步驟,我們成功實現了一個簡單的數據綁定示例。 ...
  • 是在MVVM中用來傳遞消息的一種方式。它是在MVVMLight框架中提供的一個實現了IMessenger介面的類,可以用來在ViewModel之間、ViewModel和View之間傳遞消息。 Send 接受一個泛型參數,表示要發送的消息內容。 Register 方法用於註冊某個對象接收消息。 pub ...
  • 概述:在WPF中,通過EventHandler可實現基礎和高級的UI更新方式。基礎用法涉及在類中定義事件,併在UI中訂閱以執行更新操作。高級用法藉助Dispatcher類,確保在非UI線程上執行操作後,通過UI線程更新界面。這兩種方法提供了靈活而可靠的UI更新機制。 在WPF(Windows Pre ...
  • 概述:本文介紹了在C#程式開發中如何利用自定義擴展方法測量代碼執行時間。通過使用簡單的Action委托,開發者可以輕鬆獲取代碼塊的執行時間,幫助優化性能、驗證演算法效率以及監控系統性能。這種通用方法提供了一種便捷而有效的方式,有助於提高開發效率和代碼質量。 在軟體開發中,瞭解代碼執行時間是優化程式性能 ...
  • 概述:Cron表達式是一種強大的定時任務調度工具,通過配置不同欄位實現靈活的時間規定。在.NET中,Quartz庫提供了簡便的方式配置Cron表達式,實現精準的定時任務調度。這種靈活性和可擴展性使得開發者能夠根據需求輕鬆地制定和管理定時任務,例如每天備份系統日誌或其他重要操作。 Cron表達式詳解 ...
  • 概述:.NET提供多種定時器,如System.Windows.Forms.Timer適用於UI,System.Web.UI.Timer用於Web,System.Diagnostics.Timer用於性能監控,System.Threading.Timer和System.Timers.Timer用於一般 ...
  • 問題背景 有同事聯繫我說,在生產環境上,訪問不了我負責的common服務,然後我去檢查common服務的health endpoint, 沒問題,然後我問了下異常,timeout導致的System.OperationCanceledException。那大概率是客戶端的問題,會不會是埠耗盡,用ne ...
  • 前言: 在本篇 Taurus.MVC WebMVC 入門開發教程的第四篇文章中, 我們將學習如何實現數據列表的綁定,通過使用 List<Model> 來展示多個數據項。 我們將繼續使用 Taurus.Mvc 命名空間,同時探討如何在視圖中綁定並顯示一個 Model 列表。 步驟1:創建 Model ...