一、前言
sort() 排序在实际项目中是经常用到的。刚项目中遇到比较复杂数据的排序,写点东西,记一下心得。
二、心得
sort() 默认是按照 Unicode 码顺序升序排列,会修改原数组,也会返回一个新数组。
sort() 方法里传入比较器函数自定义比较规则。
[3,2,1].sort((a,b) => {
// 内部只要写比较 a,b 的代码逻辑就可以了。
// return 值是数字类型,切勿写成布尔类型。
// return 值大于等于0,两元素位置不交换;小于0,两元素位置交换
})
Examples:
1. 纯数字数组,纯数字字符串数组或组合数组排序
const arr = [9,43,22,100]; //或 ['9','43','22','100']
let newArr = arr.sort();
console.log(newArr) //[100, 22, 43, 9]
纯数字数组,纯数字字符串数组或组合不传比较器直接用 sort() 排序,是按照元素的第一位的大小进行排序的,并不是我们想要的结果。
如果想要按数字大小排列就得传入比较器函数。
const arr = [91,42,61,22];
let newArr = arr.sort((a,b) => {
return a-b; //升序
// return b-a; //倒序
// return Math.random()>.5 ? -1 : 1; //乱序
});
console.log(newArr)
2. 由字母和数字字符串组成的数组排序
字符串排序,sort() 会先对字符串的第一位的 Unicode 码进行对比,如果一样依次比较第二位,第三位...
升序直接使用 sort() 方法就行
const arr = ["a","d","fa","5","t","fw2","a31","b","e","2fs","4","0",'z9z','z6n','ng','af','7a']
let newArr = arr.sort();
console.log(newArr)
传入比较器函数可以按降序排列
const arr = ["a","d","fa","5","t","fw2","b","e","2fs","4",'z9z','z6n','af','7a'];
let newArr = arr.sort((a,b) => {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
});
console.log(newArr) //["2fs", "4", "5", "7a", "a", "af", "b", "d", "e", "fa", "fw2", "t", "z6n", "z9z"]
字符串比大小 < >,是按照字符串的 Unicode 码大小进行比较的。
这是网上找的一个例子,把数字的排序放到字母后面
function mySorter(a, b){
if (/^\d/.test(a) ^ /^\D/.test(b)) return a>b?1:(a==b?0:-1); //^是位运算,左右两边不相等返回1,相等返回0
return a>b?-1:(a==b?0:1);
}
const pyArray=["a","d","fa","5","t","fw2","a31","b","e","2fs","4","0"]
console.log((pyArray.sort(mySorter)))
3. 汉语按照拼音首字母排序
a.localeCompare(b [, locales [, options]]) 方法会按照当地的规则,采用底层操作系统提供的排序规则进行比较。返回一个数字,a 在 b 之前返回负数,a 在 b 之后返回正数,相等返回0。可以用此方法给汉语排序。
兼容 IE11。
const arr = ['中国','红火','大爷','大大','阿里'];
let newArr = arr.sort((a,b) => {
return a.localeCompare(b, 'zh-Hans-CN', {sensitivity: 'accent'});
});
console.log(newArr) //["阿里", "大大", "大爷", "红火", "中国"]
4. 数字字符串、字母、汉语和标点混合字符串数组排序
这里的字符串是包含标点,数字字符串,大小写字母,汉字混合类型的字符串。
const rooms = [
{name: "-100"},
{name: "1-00"},
{name: "111"},
{name: "103"},
{name: "101"},
{name: "%202"},
{name: "?"},
{name: "1?"},
{name: "%3"},
{name: "@"},
{name: "Z"},
{name: "D"},
{name: "y"},
{name: "d"},
{name: "是"},
{name: "啊"},
{name: "201他"},
];
rooms.sort(locale);
console.log(rooms);
function locale(a, b) {
return a.name.localeCompare(b.name, 'zh-Hans-CN', {sensitivity: 'variant'});
}
这种方法排出的默认顺序是:符号,数字0-9,汉字,小写在前大写在后字母Aa-Zz。
自定义的排序顺序:空字符串,数字,大写,小写,汉字,标点及特殊字符。
(感觉应该还有很多可以优化的地方):
//空-1,数字字母1,汉字2,符号3
const standard = /[a-zA-Z0-9]/; //1
const hanzi = /[\u4e00-\u9fa5]/; //2
const rooms = [
{name: "-100"},
{name: "1-00"},
{name: "111"},
{name: "103"},
{name: "101"},
{name: "?"},
{name: "1?"},
{name: "%3"},
{name: "@"},
{name: "Z"},
{name: "大"},
{name: "D"},
{name: "y"},
{name: "d"},
{name: "是"},
{name: "啊"},
{name: "201他"},
{name: "201按"},
];
rooms.sort(sortFunc);
console.log(rooms);
function sortFunc(a, b) {
a = a.name;
b = b.name;
let max = a.length;
if(b.length > max) {
max = b.length;
}
for(let i=0; i<max; i++) {
if(type(a[i]) > type(b[i])) {
return 1;
}else if(type(a[i]) === type(b[i])){
if(a[i] !== b[i]) {
if(type(a[i]) === 1 || type(a[i]) === 3) {
if(a[i] > b[i]) {
return 1;
}else if(a[i] < b[i]) {
return -1;
}
}else if(type(a[i]) === 2) {
return a[i].localeCompare(b[i], 'zh-Hans-CN', {sensitivity: 'accent'})
}
}
}else {
return -1;
}
}
}
//判断当前位的字符串的类型
function type (str) {
let n;
if(!str) {
n = -1;
}else if(standard.test(str)) {
n = 1;
}else if(hanzi.test(str)) {
n = 2;
}else {
n = 3;
}
return n;
}
三、sort底层的实现机制
数组长度 <= 22 时,采用插入排序;> 22 时,采用快速排序。