【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()方法 ——解決null、undefined、0之間的排序 ...


此博客主要介紹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
更多相關文章
  • 現如今,手機錄屏是必不可少的能力之一。對於游戲領域作者來說,在平時直播玩游戲、製作攻略、操作集錦時,不方便切屏,這時在游戲內如果有一個錄製按鈕就可以隨時開啟,記錄下每個精彩瞬間,減少後期剪輯工作量;在直播App中開啟一鍵錄屏,不光方便主播後續的賬號運營與復盤,用戶也能隨時截取有意思的片段傳播在社交媒 ...
  • #背景 webpack構建過程中的hooks都有什麼呢?除了在網上看一些文章,還可以通過更直接的辦法,結合官方文檔快速讓你進入webpack的hook世界 寫一個入口文件 //index.js const webpack = require("webpack"); const path = requ ...
  • 語言基礎-變數 前言 從本篇博客開始 博主個人認為重要的知識點都會在在行前添加 ⭐ 來進行標識 變數 ECMASCRIPT變數是鬆散類型,意思是變數可以用於保存任何類型的數據。ECMASCRIPT中有三個關鍵字可以來聲明變數:var、let和const。 值得註意的是let和const只能在ES6以 ...
  • React Or Taro 項目配置Eslint校驗 一、下載Eslint相關deps依賴項; npm install --save-dev eslint-plugin-prettier eslint-plugin-jsx-a11y eslint-config-airbnb 註意:由於eslint- ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一.需求來源 今天碰到了一個需求,需要在頁面里,用水平瀑布流的方式,將一些圖片進行載入,這讓我突然想起我很久以前寫的一篇文章《JS兩種方式實現水平瀑布流佈局》 但是有個問題,這個需求是Vue項目的,那沒辦法,這裡給大家分享下我的開發過程, ...
  • 一、常見的圖片格式 BMP 是無損的、既支持索引色也支持直接色的點陣圖。這種圖片格式幾乎沒有對數據進行壓縮,所以BMP格式的圖片通常是較大的文件。 GIF 是無損的、採用索引色的點陣圖。採用LZW壓縮演算法進行編碼。文件小,是GIF格式的優點,同時,GIF格式還具有支持動畫以及透明的優點。但是GIF格 ...
  • 效果 之前: 之後 Code <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>菜鳥教程(runoob.com)</title> </head> <body> <div class="rect"> <img src="https: ...
  • vue組件中最常見的數據傳遞就是父子組件之間的傳遞,父組件可以通過 props 向下傳數據給子組件,子組件可以通過 $emit 事件攜帶數據給父組件。然而當兩個頁面沒有任關係,該如何通信?這就引出了 EventBus ( 事件匯流排 ) 這個概念 初始化 方法一:新建文件 首先需要初始化一個 Even ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...