【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
  • 1.部署歷史 猿友們好,作為初來實習的我,已經遭受社會的“毒打”,所以請容許我在下麵環節適當吐槽,3Q! 傳統部署 ​ 回顧以往在伺服器部署webapi項目(非獨立發佈),dotnet環境、守護進程兩個逃都逃不掉,正常情況下還得來個nginx代理。不僅僅這仨,可能牽扯到yum或npm。node等都要 ...
  • 隨著技術的進步,跨平臺開發已經成為了標配,在此大背景下,ASP.NET Core也應運而生。本文主要基於ASP.NET Core+Element+Sql Server開發一個校園圖書管理系統為例,簡述基於MVC三層架構開發的常見知識點,前一篇文章,已經簡單介紹瞭如何搭建開發框架,和登錄功能實現,本篇... ...
  • 這道題只要會自定義cmp恰當地進行排序,其他部分沒有什麼大問題。 上代碼: 1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,s,h1,h2,cnt; 4 struct apple{ 5 int height,ns;//height為蘋 ...
  • 這篇文章主要描述RPC的路由策略,包括為什麼需要請求隔離,為什麼不在註冊中心中實現請求隔離以及不同粒度的路由策略。 ...
  • 簡介: 中介者模式,屬於行為型的設計模式。用一個中介對象來封裝一系列的對象交互。中介者是各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變他們之間的交互。 適用場景: 如果平行對象間的依賴複雜,可以使用中介者解耦。 優點: 符合迪米特法則,減少成員間的依賴。 缺點: 不適用於系統出現對 ...
  • 【前置內容】Spring 學習筆記全系列傳送門: Spring學習筆記 - 第一章 - IoC(控制反轉)、IoC容器、Bean的實例化與生命周期、DI(依賴註入) Spring學習筆記 - 第二章 - 註解開發、配置管理第三方Bean、註解管理第三方Bean、Spring 整合 MyBatis 和 ...
  • 簡介: 享元模式,屬於結構型的設計模式。運用共用技術有效地支持大量細粒度的對象。 適用場景: 具有相同抽象但是細節不同的場景中。 優點: 把公共的部分分離為抽象,細節依賴於抽象,符合依賴倒轉原則。 缺點: 增加複雜性。 代碼: //用戶類 class User { private $name; fu ...
  • 這次設計一個通用的多位元組SPI介面模塊,特點如下: 可以設置為1-128位元組的SPI通信模塊 可以修改CPOL、CPHA來進行不同的通信模式 可以設置輸出的時鐘 狀態轉移圖和思路與多位元組串口發送模塊一樣,這裡就不給出了,具體可看該隨筆。 一、模塊代碼 1、需要的模塊 通用8位SPI介面模塊 `tim ...
  • AOP-03 7.AOP-切入表達式 7.1切入表達式的具體使用 1.切入表達式的作用: 通過表達式的方式定義一個或多個具體的連接點。 2.語法細節: (1)切入表達式的語法格式: execution([許可權修飾符] [返回值類型] [簡單類名/全類名] [方法名]([參數列表]) 若目標類、介面與 ...
  • 測試一、虛繼承與繼承的區別 1.1 單個繼承,不帶虛函數 1>class B size(8): 1> + 1> 0 | + (base class A) 1> 0 | | _ia //4B 1> | + 1> 4 | _ib //4B 有兩個int類型數據成員,占8B,基類邏輯存在前面 1.2、單個 ...