【JavaScript 教程】第六章 數(shù)組10— sort() : 對數(shù)組中的元素進(jìn)行排序

英文 | https://www.javascripttutorial.net/
譯文 | 楊小愛
JavaScript Array sort() 方法介紹
sort() 方法允許您就地對數(shù)組的元素進(jìn)行排序。除了返回排序后的數(shù)組,sort() 方法還改變了元素在原始數(shù)組中的位置。
默認(rèn)情況下, sort() 方法按升序?qū)?shù)組元素進(jìn)行排序,最小值在前,最大值在后。
sort() 方法將元素轉(zhuǎn)換為字符串并比較字符串以確定順序。
考慮以下示例:
let numbers = [0, 1 , 2, 3, 10, 20, 30 ];numbers.sort();console.log(numbers);
輸出是:
[ 0, 1, 10, 2, 20, 3, 30 ]
在此示例中,sort() 方法將 10 放在 2 之前,因?yàn)樵谶M(jìn)行字符串比較時,字符串“10”在“2”之前。
要解決此問題,您需要將比較函數(shù)傳遞給 sort() 方法。 sort() 方法將使用比較函數(shù)來確定元素的順序。
下面說明了 sort() 方法的語法:
array.sort(comparefunction)
sort() 方法接受一個可選參數(shù),該參數(shù)是一個比較數(shù)組兩個元素的函數(shù)。
如果省略 compare 函數(shù),sort() 方法將按照前面提到的基于元素的 Unicode 代碼點(diǎn)值的排序順序?qū)υ剡M(jìn)行排序。
sort() 方法的比較函數(shù)接受兩個參數(shù)并返回一個確定排序順序的值。 下面說明了比較函數(shù)的語法:
function compare(a,b) {// ...}
compare() 函數(shù)接受兩個參數(shù) a 和 b。 sort() 方法將根據(jù) compare() 函數(shù)的返回值使用以下規(guī)則對元素進(jìn)行排序:
如果 compare(a,b) 小于零,sort() 方法將 a 排序到比 b 低的索引。 換句話說,a 會先出現(xiàn)。
如果 compare(a,b) 大于零,則 sort() 方法將 b 排序?yàn)楸?a 低的索引,即 b 將排在最前面。
如果 compare(a,b) 返回零,則 sort() 方法認(rèn)為 a 等于 b 并保持它們的位置不變。
要解決排序數(shù)字的問題,您可以使用以下語法:
let numbers = [0, 1 , 2, 3, 10, 20, 30 ];numbers.sort( function( a , b){if(a > b) return 1;if(a < b) return -1;return 0;});console.log(numbers);
輸出:
[ 0, 1, 2, 3, 10, 20, 30 ]
或者您可以使用箭頭函數(shù)語法定義比較函數(shù):
let numbers = [0, 1 , 2, 3, 10, 20, 30 ];numbers.sort((a,b) => {if(a > b) return 1;if(a < b) return -1;return 0;});console.log(numbers);
以下是最簡單的,因?yàn)閿?shù)組的元素是數(shù)字:
let numbers = [0, 1, 2, 3, 10, 20, 30];numbers.sort((a, b) => a - b);console.log(numbers);
對字符串?dāng)?shù)組進(jìn)行排序
假設(shè)您有一個名為動物的字符串?dāng)?shù)組,如下所示:
let animals = ['cat', 'dog', 'elephant', 'bee', 'ant'];
要按字母順序?qū)游飻?shù)組的元素進(jìn)行升序排序,請使用 sort() 方法而不傳遞 compare 函數(shù),如下例所示:
let animals = ['cat', 'dog', 'elephant', 'bee', 'ant'];animals.sort();console.log(animals);
輸出:
[ 'ant', 'bee', 'cat', 'dog', 'elephant' ]
要按降序?qū)游飻?shù)組進(jìn)行排序,您需要更改比較函數(shù)的邏輯并將其傳遞給 sort() 方法,如下例所示。
let animals = ['cat', 'dog', 'elephant', 'bee', 'ant'];animals.sort((a, b) => {if (a > b)return -1;if (a < b)return 1;return 0;});console.log(animals);
輸出:
[ 'elephant', 'dog', 'cat', 'bee', 'ant' ]
假設(shè)您有一個包含大寫和小寫元素的數(shù)組,如下所示:
// sorting array with mixed caseslet mixedCaseAnimals = ['Cat', 'dog', 'Elephant', 'bee', 'ant'];
要按字母順序?qū)Υ藬?shù)組進(jìn)行排序,您需要使用自定義比較函數(shù)將所有元素轉(zhuǎn)換為相同的大小寫,例如大寫進(jìn)行比較并將該函數(shù)傳遞給 sort() 方法。
let mixedCaseAnimals = ['Cat', 'dog', 'Elephant', 'bee', 'ant'];mixedCaseAnimals.sort(function (a, b) {let x = a.toUpperCase(),y = b.toUpperCase();return x == y ? 0 : x > y ? 1 : -1;});
輸出:
[ 'ant', 'bee', 'Cat', 'dog', 'Elephant' ]
使用非 ASCII 字符對字符串?dāng)?shù)組進(jìn)行排序
sort() 方法可以很好地處理帶有 ASCII 字符的字符串。 但是,對于包含非 ASCII 字符(例如 é、è 等)的字符串,sort() 方法將無法正常工作。 例如:
let animaux = ['zèbre', 'abeille', 'écureuil', 'chat'];animaux.sort();console.log(animaux);
如您所見,écureuil 字符串應(yīng)該在 zèbre 字符串之前。
要解決此問題,您可以使用 String 對象的 localeCompare() 方法來比較特定語言環(huán)境中的字符串,如下所示:
animaux.sort(function (a, b) {return a.localeCompare(b);});console.log(animaux);
輸出:
[ 'abeille', 'chat', 'écureuill', 'zèbree' ]
animaux 數(shù)組的元素現(xiàn)在處于正確的順序。
對數(shù)字?jǐn)?shù)組進(jìn)行排序
假設(shè)您有一個名為分?jǐn)?shù)的數(shù)字?jǐn)?shù)組,如下例所示。
let scores = [9, 80, 10, 20, 5, 70];
要按數(shù)字對數(shù)字?jǐn)?shù)組進(jìn)行排序,您需要傳入一個自定義比較函數(shù)來比較兩個數(shù)字。
以下示例按數(shù)字升序?qū)Ψ謹(jǐn)?shù)數(shù)組進(jìn)行排序。
let scores = [9, 80, 10, 20, 5, 70];// sort numbers in ascending orderscores.sort((a, b) => a - b);console.log(scores);
輸出:
[ 5, 9, 10, 20, 70, 80 ]
要以降序?qū)?shù)字?jǐn)?shù)組進(jìn)行排序,您只需要反轉(zhuǎn)比較函數(shù)中的邏輯,如下例所示:
let scores = [9, 80, 10, 20, 5, 70];// descending orderscores.sort((a, b) => b - a);console.log(scores);
輸出:
[80, 70, 20, 10, 9, 5]
按指定屬性對對象數(shù)組進(jìn)行排序
下面是一個employee對象數(shù)組,其中每個對象包含三個屬性:name、salary和hireDate。
let employees = [{name: 'John', salary: 90000, hireDate: "July 1, 2010"},{name: 'David', salary: 75000, hireDate: "August 15, 2009"},{name: 'Ana', salary: 80000, hireDate: "December 12, 2011"}];
按數(shù)字屬性對對象進(jìn)行排序
以下示例顯示如何按salary升序?qū)T工進(jìn)行排序。
// sort by salaryemployees.sort(function (x, y) {return x.salary - y.salary;});console.table(employees);
輸出:

此示例類似于按升序?qū)?shù)字?jǐn)?shù)組進(jìn)行排序的示例。 不同之處在于它比較了兩個對象的salary屬性。
按字符串屬性對對象進(jìn)行排序
要按name屬性不區(qū)分大小寫對employees數(shù)組進(jìn)行排序,請傳遞比較兩個字符串不區(qū)分大小寫的比較函數(shù),如下所示:
employees.sort(function (x, y) {let a = x.name.toUpperCase(),b = y.name.toUpperCase();return a == b ? 0 : a > b ? 1 : -1;});console.table(employees);

按日期屬性對對象進(jìn)行排序
假設(shè)您希望根據(jù)每個員工的雇用日期對員工進(jìn)行排序。
雇用日期數(shù)據(jù)存儲在雇員對象的租用日期屬性中。 但是,它只是一個表示有效日期的字符串,而不是 Date 對象。
因此,要按雇用日期對員工進(jìn)行排序,首先必須從日期字符串創(chuàng)建一個有效的 Date 對象,然后比較兩個日期,這與比較兩個數(shù)字相同。
這是解決方案:
代碼語言:JavaScript ( javascript )employees.sort(function (x, y) {let a = new Date(x.hireDate),b = new Date(y.hireDate);return a - b;});console.table(employees);

優(yōu)化 JavaScript 數(shù)組 sort() 方法
實(shí)際上,sort() 方法為數(shù)組中的每個元素多次調(diào)用比較函數(shù)。
請參閱以下示例:
let rivers = ['Nile', 'Amazon', 'Congo', 'Mississippi', 'Rio-Grande'];rivers.sort(function (a, b) {console.log(a, b);return a.length - b.length;});
輸出:
Amazon NileCongo AmazonCongo AmazonCongo NileMississippi CongoMississippi AmazonAmazonMississippi
它們怎么運(yùn)行的:
首先,聲明一個由著名河流名稱組成的數(shù)組 rivers。
其次,使用 sort() 方法按其元素的長度對rivers數(shù)組進(jìn)行排序。每當(dāng) sort() 方法調(diào)用比較函數(shù)時,我們就會將 Rivers 數(shù)組的元素輸出到 Web 控制臺。
如上面的輸出所示,每個元素都被評估了多次,例如亞馬遜 4 次,剛果 2 次等。
如果數(shù)組元素的數(shù)量增加,則可能會降低性能。
您無法減少比較函數(shù)的執(zhí)行次數(shù)。但是,您可以減少比較必須執(zhí)行的工作。這種技術(shù)稱為施瓦茲變換。
要實(shí)現(xiàn)這一點(diǎn),請按照以下步驟操作:
首先,使用 map() 方法將實(shí)際值提取到臨時數(shù)組中。
其次,使用已經(jīng)評估(或轉(zhuǎn)換)的元素對臨時數(shù)組進(jìn)行排序。
第三,遍歷臨時數(shù)組,得到一個順序正確的數(shù)組。
這是解決方案:
// temporary array holds objects with position// and length of elementvar lengths = rivers.map(function (e, i) {return {index: i, value: e.length };});// sorting the lengths array containing the lengths of// river nameslengths.sort(function (a, b) {return +(a.value > b.value) || +(a.value === b.value) - 1;});// copy element back to the arrayvar sortedRivers = lengths.map(function (e) {return rivers[e.index];});console.log(sortedRivers);
輸出:
[ 'Nile', 'Congo', 'Amazon', 'Rio-Grande', 'Mississippi' ]
在本教程中,我們學(xué)習(xí)了如何使用 JavaScript Array sort()方法對字符串、數(shù)字、日期和對象數(shù)組進(jìn)行排序。
今天的內(nèi)容就到這里了。
如果您還想學(xué)習(xí)更多關(guān)于數(shù)組的內(nèi)容,請點(diǎn)擊下文鏈接進(jìn)行學(xué)習(xí)。
【JavaScript 教程】第六章 數(shù)組09— some() :檢查數(shù)組中是否至少有一個元素通過了測試
【JavaScript 教程】第六章 數(shù)組08— every() :檢查數(shù)組中的每個元素是否都通過了測試
【JavaScript 教程】第六章 數(shù)組07— index() :在數(shù)組中定位一個元素
【JavaScript 教程】第六章 數(shù)組06— slice() :復(fù)制數(shù)組元素
【JavaScript 教程】第六章 數(shù)組05— splice():刪除、插入和替換
【JavaScript 教程】第六章 數(shù)組04— JavaScript 隊列
【JavaScript 教程】第六章 數(shù)組03— Stack :使用 Array 的push()和pop()方法實(shí)現(xiàn)堆棧數(shù)據(jù)結(jié)構(gòu)
【JavaScript 教程】第六章 數(shù)組02— Array Length:如何有效地使用數(shù)組的長度屬性
【JavaScript 教程】第六章 數(shù)組01— 介紹JavaScript中的Array類型
學(xué)習(xí)更多技能
請點(diǎn)擊下方公眾號
![]()

