Re0:从零开始的JavaScript - sort 踩坑记 && 多条件排序

多条件排序

有个这么个要求,给一组数组

var data = [
    {a:1,b:2},
    {a:2,b:5},
    {a:3,b:4},
    {a:2,b:7},
    {a:1,b:2},
    {a:2,b:7},
    {a:4,b:8},
    {a:2,b:123},
    {a:5,b:23},
]

要求a从小到大排序,a相等的b从大到小排序


首先实现属性a从小到大排序

data.sort(function(a,b) {
    return a.a - b.a
})

接着继续掉调用把属性a排序好的数组

data.sort(function(a,b) {
    return a.a - b.a
}).sort(function(a,b) {
    // 如果a属性相等则进行比较,否则不改变位置
    if(a.a === b.a) {
        return b.b - a.b
    } else {
        return -1
    }
})
console.log(data)

打印一下,也没问题。本以为就这样能搞定的我,还是图样了。

当我把数组的元素增加多几个的时候:

var data = [
    {a:1,b:2},
    {a:2,b:5},
    {a:3,b:4},
    {a:2,b:7},
    {a:1,b:2},
    {a:2,b:7},
    {a:4,b:8},
    {a:2,b:123},
    {a:5,b:23},
    {a:1,b:23},
    {a:2,b:55},
    {a:4,b:8},
    {a:2,b:12},
    {a:5,b:33},
]

问题就来了,使用上面的方法排序,完全得不到预想的结果。

这明明刚才还可以的怎么增加一点数据就完全变样了呢,所谓一言不合看源码。还真是有道理

v8 array部分源码 (搜索“InnerArraySort”)

可以看到该方法首行就备注了

// In-place QuickSort algorithm.
// For short (length <= 10) arrays, insertion sort is used for efficiency.

V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。

快排不像插入排序,从后往前扫相邻的两个元素进行比较,而是找基准,遍历数组,小于基准的放在left,大于基准的放在right,递归

修改后的方法

data.sort((a, b) => {
    return a.a === b.a ? ( a.b - b.b ) : a.a - b.a;
})

封装一下

var by = function(name, minor){
    return function(o, p) {
        var a, b;
        a = o[name];
        b = p[name];
        if (a === b) {
            return typeof minor === 'function' ? minor(o,p) : 0;
        }
        if (typeof a === typeof b) {
            return a < b ? -1 : 1;
        }
    }
}

data.sort(by('age',by('sin')));

你可能感兴趣的:(Re0:从零开始的JavaScript - sort 踩坑记 && 多条件排序)