Array.prototype.sort 是否具有稳定性

70 阅读1分钟

起因

最近在写sort排序的时候发现一个问题:

// 数据结构
const originData = [
    { value: 1, disabled: true },
    { value: 2, disabled: false },
    { value: 3, disabled: true },
    { value: 4, disabled: false },
    { value: 5, disabled: true },
    { value: 6, disabled: false },
    { value: 7, disabled: true },
    { value: 8, disabled: false },
    { value: 9, disabled: true },
    { value: 10, disabled: false },
    { value: 11, disabled: true },
]
// 排序算法
originData.sort(pre => pre.disabled ? 1 : -1);

原本是想把所有的disabled为true的数据放在后面的,可得到的结果如下:

image.png 确实是成功实现了需求,但是为啥原有的顺序变了呢?难道sort是非稳定的嘛?

探究

直接翻出v8对sort方法稳定性的说明:v8.dev/features/st…

image.png 说了一堆,其实就是说之前sort是非稳定的,对大数组的排序会乱序,但是现在各个浏览器已经逐步支持稳定的sort排序了。 而且这文章是19年的,现在sort函数应该是稳定的没问题。

那么为什么我这样实现出问题了呢?打开MDN对sort方法的说明:

image.png

额,看了sort函数返回值的说明,发现我上面sort的函数存在问题,只考虑了前一个数的disabled值,在前后两个disabled同时为ture或同时为false时,会直接调换顺序,从而破坏稳定性。

改良排序方法

sort((pre, next) => (pre.disabled ? (next.disabled ? 0 : 1) : (next.disabled ? -1 : 0)));

image.png

得到符合预期的结果

结论

  1. sort是稳定排序的。
  2. sort的回调函数必须仔细考虑前后两个参数的各种情况,返回排序的结果,避免产生上述错误。