[譯] 正確使用 sort() 方法

英文原文: 《Usar correctamente el método sort()》
注意:內容有作精簡和調整。ios

在過去的幾個星期裏,咱們在不一樣的團隊中看到,通常來講都沒有使用 Array.prototype.sort() 的習慣,而且不知道這種方法是如何工做的。今天咱們將嘗試簡要描述它是如何工做的 .sort(),咱們將揭示它的一些祕密。git

1. 修改原數組

在這種狀況下,咱們必須記住,此方法經過對數組進行排序來修改數組返回相同的有序數組,但不返回新數組。若是咱們想要保持數組不可變並得到另外一個排序,這一點很重要,咱們必須在排序以前製做數組的拷貝。github

2. 字符串在 Unicode 代碼中的位置比較

默認狀況下,.sort() 方法會根據 Unicode 代碼中每一個字母的位置將數組值排序爲字符串,所以您能夠對此數組進行排序而不會出現問題:json

console.log(["Zaragoza", "Madrid", "Barcelona"].sort());
// [ 'Barcelona', 'Madrid', 'Zaragoza' ]
複製代碼

這彷佛是正確的,可是若是和一些名稱以小寫字母開頭,那麼排序彷佛不正確:數組

console.log(["Zaragoza", "madrid", "Barcelona"].sort());
// [ 'Barcelona', 'Zaragoza', 'madrid' ]
複製代碼

在這種狀況下,排序是在 Unicode 代碼表中的每一個字母的位置以後完成的,而且 m 落後 Z ,所以它已經以這種方式排序。瀏覽器

若是咱們想對數字排序,事情就會變得複雜起來:微信

console.log([80, 9, 100].sort());
// [ 100, 80, 9 ]
複製代碼

結果彷佛很荒謬,但這是有道理的,發生的事情是數字已被轉換爲字符串,所以被比較的是字符串"100""80"而且"9"。因爲它們在 Unicode 代碼中的位置是按順序的,所以排序是正確的,即便它不是咱們最初的預期。數據結構

這些狀況的產生致使一些人放棄使用 .sort() 產生混亂的行爲。這有點草率,由於只需一點幫助,這種方法能夠毫無問題地運行。函數

3. Sort() 方法參數

.sort()一個可選參數容許此方法幫助對內容進行排序。這是此方法的關鍵,由於咱們對每種狀況都感興趣。工具

此函數接收兩個要比較的值,所以也會有這麼三種狀況:

  • 若是第一個值大於第二個值,則返回正值 (1);
  • 若是第一個值小於第二個值,則返回負值 (-1);
  • 若是兩個值相等或等效於排序,則返回零值 (0);

這個函數由 Javascript 調用,只要您須要對數組中的元素進行排序,咱們就能夠進行必要的比較和調整。例如,爲了比較數字,咱們可使用相似方法:

console.log([80, 9, 100].sort((a, b) => a - b));
// [ 9, 80, 100 ]
複製代碼

另外,(a, b) => a – b 還能夠這麼使用:使用其中一個值 a 去判斷是否大於另外一個值 b 來返回排序結果:

const data = [ "Zaragoza", "madrid", "Barcelona" ];
data.sort ((a, b) => a.toLowerCase () > b.toLowerCase ());
console.log (data);
// [ 'Zaragoza', 'madrid', 'Barcelona' ]
複製代碼

顯然結果不正確,由於咱們草率的將函數比較的結果 true 或者 false 返回,咱們必須記住支持函數 .sort() 但願咱們返回 -11 或者 0。爲了使它正常運行,咱們必須作修改:

const data = [ "Zaragoza", "madrid", "Barcelona" ];
data.sort ((a, b) =>
  a.toLowerCase() > b.toLowerCase() ? 1 :
  a.toLowerCase() < b.toLowerCase() ? -1:
  0
);
console.log (data);
// [ 'Barcelona', 'madrid', 'Zaragoza' ]
複製代碼

如今的結果是咱們須要的,由於咱們已經對小寫和大寫也進行了比較,而且咱們已經返回-11或者0根據每種狀況。

咱們尚未真正完成,由於若是咱們加入一些重音字母,咱們會獲得一個不但願的結果:

const data = [ "Zaragoza", "madrid", "Barcelona", "Ávila" ];

data.sort ((a, b) =>
  a.toLowerCase() > b.toLowerCase() ? 1 :
  a.toLowerCase() < b.toLowerCase() ? -1:
  0
);
console.log (data);
// [ 'Barcelona', 'madrid', 'Zaragoza', 'Ávila' ]
複製代碼

當咱們想對文本字符串進行排序,就很是有必要使用 .localeCompare() 方法,也是很是重要。

4. 用對象屬性排序數組

一般,若是數組包含對象,咱們可使用對象的屬性進行比較,例如:

const data = require ('./municipios.json');
data.sort ((a, b) => a.municipio.localeCompare (b.municipio));
複製代碼

咱們能夠對數據結構中的日期和任何其餘類型的對象執行相同的操做。

5. 關於性能方面

若是咱們想對很是大的數組進行排序,咱們必須記住。sort() 方法的支持函數將被屢次調用,咱們必須避免在這個函數中執行許多操做或很是重的操做。咱們必須儘量有效地進行比較。

例如,在很是大的數組中,可使用新的方法 Int.Collate().compare 來得到更有效的排序函數,而不是使用 .localecompare()Int 對象是名爲 International API ,也是 ECMA-402 的標準的一部分,

該標準側重於國際化功能,包括每種語言的正確排序Int 在瀏覽器和節點中以全局對象的形式呈現,並具備普遍的支持(包括IE11)。

const data    = [ "Zaragoza", "Ávila", "madrid", "Barcelona" ];
const compare = new Intl.Collator ().compare;
data.sort (compare);
console.log (data);
// [ 'Ávila', 'Barcelona', 'madrid', 'Zaragoza' ]
複製代碼

排序操做很複雜,性能也不好,所以對於很是大的數組,排序方法支持函數速度的任何改進都將對性能產生很是顯著的影響。

6. 總結

通常來講,咱們應該利用 .sort() 功能和一個支持函數來控制排序應該如何執行:

  • 數字: (a, b) => a – b
  • 鏈式: (a, b) => a.localeCompare(b)

在沒有函數參數的狀況下使用 .sort() 是沒有意義的,也許在少數狀況下是這樣,可是若是咱們用一個簡單的函數支持它,那麼 .sort 是一個很是有用的工具。

在許多狀況下,排序是一個基本的操做,咱們不該該放棄在Javascript中進行這種排序。

關於我

本文首發在 pingan8787我的博客,如需轉載請保留我的介紹。

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 github.com/pingan8787/…
ES小冊 js.pingan8787.com

微信公衆號

bg
相關文章
相關標籤/搜索