一、前言

      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 时,采用快速排序。