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,都会是降序。
假如在面试中可以透过这样的例子说明,相信能够通过这个题目。