sort函数的返回值为经过排序的原始数组的引用。注意数组是就地排序的,不会进行复制。
问题:
如果数组内某一对象为空值,排序是怎样的呢?(显然并不是按年龄顺序排序的,因为存在null和undefined)
var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":0,name:'gr'},
{"age":null,name:'yo'},{"age":7,name:'pl'},{"age":undefined,name:'tt'},
{"age":null,name:'jz'},{"age":0,name:'mn'},{"age":undefined,name:'we'}]
//[{"age": 0,"name": "ls"},{"age": 0,"name": "gr"},{"age": null,"name": "yo"},
//{"age": null,"name": "jz"},{"age": 0,"name": "mn"},{"age": 7,"name": "pl"},
//{"age": 24,"name": "zs"},{"age":undefined,"name": "tt"},
//{"age":undefined,"name": "we"}]
console.log(arr.sort(compare("age")));
单纯数组和对象数组的表现还不一样,如下:
解决方法:
sort 方法提供的排序方法中,如果返回的数字是 0 那么会保持原顺序,如果返回的数字 >0 那么会将 a 至于 b 之后,如果返回的数字 < 0 那么会将 a 至于 b 之前。
如果遇到字段可能是 undefined,那么我们需要特殊判断处理下。
首先判断如果 a,b 的排序字段都是 undefined 返回 0 保持原顺序。
再判断如果 a 的字段是 undefined 但 b 的排序字段存在则返回 >0 将 a 至于 b 之后。
再判断 b 的排序字段如果是 undefined 但 a 的排序字段存在则返回 <0 将 a 至于 b 之前。
最后 a,b 的排序字段都存在时,使用 a,b 的排序字段计算后的返回结果判断顺序
const compare = function (orderType, props) {
return function (obj1, obj2) {
var val1 = obj1[props];
var val2 = obj2[props];
if (val1 == null && val2 == null) {
return 0;
}
if(val1 == null){
return 999;
}
if(val2 == null){
return -999
}
if (typeof val1 === 'string' && typeof val2 === 'string') {
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
}
return 0;
}
return orderType === 'ascend' ? val1 - val2 : val2 - val1;
}
}
const orderType = 'descend'; // descend
const rr = prodInfo.sort(compare(orderType, 'num'))
console.log(rr.map(item => item.num))
参考链接1:https://www.cnblogs.com/gby-web/p/16743564.html
参考链接2:https://juejin.cn/post/7165121725678665765/
双重排序(二次排序):
二次排序是指对数据进行两次排序,第一次按照某个属性进行排序,第二次按照另一个属性进行排序。这种排序方法可以用于多种场景,例如对学生按照成绩和年龄进行排序,对商品按照价格和销量进行排序等等。在实现二次排序时,可以使用多种算法,例如冒泡排序、快速排序、归并排序等等。需要根据具体的场景和数据量选择最适合的算法。
/**
* 二次排序
*/
const productInfo = [
{
category: 'apple',
price: 5
}, {
category: 'apple',
price: undefined
}, {
category: 'apple',
price: 2
}, {
category: 'pear',
price: undefined
}, {
category: 'grape',
price: null
}, {
category: 'banana',
price: 7
}, {
category: 'orange',
price: 3
}
]
// 初版
// const orderProdInfo = productInfo.sort((a, b) => {
// if (a['category'] < b['category']) {
// return -1;
// } else if (a['category'] > b['category']) {
// return 1;
// } else {
// // 第一层排序相等情况,处理第二层排序
// return a['price'] - b['price']
// }
// });
// console.log(productInfo)
// 函数抽取
function compareCore(compareFn) {
return (l, r) => {
if (l == null && r == null) {
return 0;
}
if (l == null && r) {
return 1
}
if (l && r == null) {
return -1;
}
return compareFn(l, r);
}
}
const numberCompare = compareCore((l, r) => l - r);
const stringCompare = compareCore((l, r) => {
if (l < r) {
return -1;
} else if (l > r) {
return 1;
} else {
return 0;
}
})
// 业务逻辑
const priceCompare = (l, r) => {
return numberCompare(l['price'], r['price'])
}
const cateCompare = (l, r) => {
return stringCompare(l['category'], r['category']);
}
// 双重排序
const doubleCompare = (l, r) => {
if (cateCompare(l, r) === 0) {
return priceCompare(l, r);
}
return cateCompare(l, r);
}
const orderProdInfo = productInfo.sort((l, r) => {
return doubleCompare(l, r)
});
console.log(orderProdInfo)
指定顺序排序
// ## 按指定序列排序
const arr = [
{ name: 'A', type: 'fly' },
{ name: 'B', type: 'blur' },
{ name: 'C', type: 'wipe' },
{ name: 'D', type: 'cube' },
{ name: 'B', type: 'zoom' },
{ name: 'C', type: 'cube' },
{ name: 'E', type: 'iris' },
{ name: 'F', type: 'fade' },
{ name: 'F', type: '' }
];
// 按type的指定顺序排序
const order = ['wipe', 'fly', 'iris', 'flip', 'cube', 'blur', 'fade', 'zoom'];
arr.sort((star, next) => {
return order.indexOf(star.type) - order.indexOf(next.type);
});
console.log(arr);
随机排序
// ## 随机排序
arr.sort((a, b) => {
return Math.random() - 0.5
})
console.log(arr);