JavaScript 中的 sort 传入 (a,b) => b - a 会是升序还是降序?为什么呢?

2022年12月18日

💎 加入 E+ 成長計畫 與超過 300+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

在 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 上追蹤我們