JavaScript 中的 sort 傳入 (a,b) => b - a 會是升序還是降序?為什麼呢?
2022年12月18日
在 JavaScript 中的陣列有內建的 sort
方法,可以讓我們不用自己手寫排序算法,也能夠有高效能的排序方法可用。然而,你知道 sort
要怎麼用嗎? 在 sort
中要傳入的 compareFn
又是如何運作的? 當 compareFn
是(a, b) => b - a
時,排序會是升序還是降序? 為什麼呢?
這一連串的問題,不僅是工作中很常用到,也是面試的高頻問題,務必確保自己這個觀念有融會貫通。假如還不熟的話,就讓我們一起透過這篇文章一探究竟。
如何使用 sort
假如看 MDN 的文件,可以看到 sort
的用法是這樣。
sort(compareFn);
其中的 compareFn
需要兩個參數 a
與 b
,在比較的規則中,一定要回傳 1
、0
或 -1
。其中要遵循的規則如下:
function compareFn(a, b) {
if (a 比 b 大) {
return 1; // 意即 a 放在 b 後面
}
if (a 比 b 小) {
return -1; // 意即 a 放在 b 前面
}
// a 等同於 b
return 0; // // 意即 a 與 b 之間的位置不變
}
不過在寫數字之間的比較時,我們往往會寫得更簡潔一點。以下面的例子來說,compareFn
即是 (a, b) => b - a
。這時就迎來一個經典的面試問題, (a, b) => b - a
會是升序還是降序? 以及為什麼?
let arr = [3, 22, 17, 35, 2, 66];
arr.sort((a, b) => b - a);
// arr 會是 [2, 3, 17, 22, 35, 66] 還是 [66, 35, 22, 17, 3, 2] ?
(a,b) => b - a
是升序或降序? 為什麼?
(a, b) => b - a
會是升序還是降序? 答案是降序,所以上面的例子中 arr
會變成 [66, 35, 22, 17, 3, 2] 。
let arr = [3, 22, 17, 35, 2, 66];
arr.sort((a, b) => b - a); // [66, 35, 22, 17, 3, 2]
反之,如果傳入的 compareFn
是 (a, b) => a - b
則會是升序,讓 arr
變成 [2, 3, 17, 22, 35, 66]。
let arr = [3, 22, 17, 35, 2, 66];
arr.sort((a, b) => a - b); // [2, 3, 17, 22, 35, 66]
為什麼會是這樣呢? 還記得我們在上一段落提到,compareFn
當中,
- 如果
a
比b
大,則回傳 1 - 如果
a
比b
小,則回傳 -1 - 如果
a
與b
相等,則回傳 0
我們接下來看以下推演:
在 (a, b) => a - b
時,
- 如果
a > b
,那a - b
會大於 0,則回傳 1,a 放在 b 後面,順序會是 b, a,因為 a 大於 b 所以是升序 - 如果
a < b
,那a - b
會小於 0,則回傳 -1,a 放在 b 前面,順序會是 a, b,因為 a 小於 b 所以結果同樣也是升序
同樣地,在 (a, b) => b - a
時,
- 如果
a > b
,那b - a
會小於 0,則回傳 -1,b 放在 a 後面,順序會是 a, b,因為 a 大於 b 所以是降序 - 如果
a < b
,那b - a
會大於 0,則回傳 1,b 放在 a 前面,順序會是 b, a,因為 a 小於 b 所以結果同樣也是降序
從上面的例子中可以看到,(a, b) => a - b
時,不論 a 大於 b,或 a 小於 b,都會是升序。反之,在 (a, b) => b - a
時,不論 a 大於 b,或 a 小於 b,都會是降序。
假如在面試中可以透過這樣的例子說明,相信能夠通過這個題目。