JavaScript 中的 sort 傳入 (a,b) => b - a 會是升序還是降序?為什麼呢?

2022年12月18日

💎 加入 E+ 成長計畫 與超過 250+ 位軟體工程師一起在社群中成長,並且獲得更深入、系統性軟體工程內容

在 JavaScript 中的陣列有內建的 sort 方法,可以讓我們不用自己手寫排序算法,也能夠有高效能的排序方法可用。然而,你知道 sort 要怎麼用嗎? 在 sort 中要傳入的 compareFn 又是如何運作的? 當 compareFn(a, b) => b - a 時,排序會是升序還是降序? 為什麼呢?

這一連串的問題,不僅是工作中很常用到,也是面試的高頻問題,務必確保自己這個觀念有融會貫通。假如還不熟的話,就讓我們一起透過這篇文章一探究竟。

如何使用 sort

假如看 MDN 的文件,可以看到 sort 的用法是這樣。

sort(compareFn);

其中的 compareFn 需要兩個參數 ab ,在比較的規則中,一定要回傳 10-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 當中,

  • 如果 ab 大,則回傳 1
  • 如果 ab 小,則回傳 -1
  • 如果 ab 相等,則回傳 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,都會是降序

假如在面試中可以透過這樣的例子說明,相信能夠通過這個題目。

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們