多条件排序
有个这么个要求,给一组数组
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')));