前文回顾:
清空数组元素,哪种方式效率更好?【length=0 】VS 【splice(0,len)】
数组如何排序?我们可以使用 sort 来实现,如果数组成员是对象的话,如何排序呢?
数字
我们先看看数组成员是数字的情况。
默认排序
const arrNumber = [1,20,11,25,81,3,8,10,11]
arrNumber.sort()
console.log('arrNumber-sort() :', arrNumber)
sort() 没有传递参数的话,就是默认排序,那么排序规则是按照数字吗?测试了一下发现,并不是按照数字,而是按照字符来排序的。
看看结果:
arrNumber-sort() : (9) [1, 10, 11, 11, 20, 25, 3, 8, 81]
先判断第一位,然后判断第二位,于是1开头的在前,后面是2开头,3开头。
升序
那么如果我们想按照数字排序怎么办?可以使用参数:
arrNumber.sort((num, next) => num - next )
前一个数和后一个数相减,按照结果进行排序,这样就是从小到大的排序。
看看结果:
arrNumber- num -> next: (9) [1, 3, 8, 10, 11, 11, 20, 25, 81]
倒序
如果想倒序怎么办?倒过来减就行
arrNumber.sort((num, next) => -num + next )
应该写成 next - num 的,但是我懒,直接改符号多简单。
看看结果:
arrNumber- next -> num: (9) [81, 25, 20, 11, 11, 10, 8, 3, 1]
字符串
字符串排序会如何呢?
默认排序
const arrString = ['1','11','a', 'v', '8a1', 'a3', '汉字', '大', '小', 'c','22']
看看结果:
arrString-sort() : (11) ["1", "11", "22", "8a1", "a", "a3", "c", "v", "大", "小", "汉字"]
sort() 默认排序,按照数字、英文、汉字的顺序排列。汉字好像不是按照拼音排序。
使用减法
尝试减法的时候,会出现提示:算术运算必须是 any、number、bigint或者枚举,但是程序可以运行,而且没有报错。好神奇的js。
arrString.sort((num, next) => num - next )
arrString.sort((num, next) => -num + next )
看看结果:
arrString- num -> next: (11) ["1", "11", "22", "8a1", "a", "a3", "c", "v", "大", "小", "汉字"]
arrString- next -> num: (11) ["22", "11", "1", "8a1", "a", "a3", "c", "v", "大", "小", "汉字"]
对比一下,只影响数字内部的排序,其他不影响。可能是先进行转换,转换失败的话,按照默认的来。
转换为 ASCII 再排序
字符串不能做减法,那么转换一下呢?
arrString.sort((num, next) => num.charCodeAt(0) - next.charCodeAt(0) )
arrString.sort((num, next) => -num.charCodeAt(0) + next.charCodeAt(0) )
看看结果:
charCodeAt- num -> next: (11) ["11", "1", "22", "8a1", "a", "a3", "c", "v", "大", "小", "汉字"]
charCodeAt- next -> num: (11) ["汉字", "小", "大", "v", "c", "a", "a3", "8a1", "22", "11", "1"]
结果很明显,可以按照第一个字符的ASCII来正序或者倒序。所以默认排序,是按照ASCII排序的。
这里只获取了第一位,没有考虑后面的,所以排序并不完全符合预期。
对象
现在我们使用数组,往往会往里面放对象,那么对象如何排序呢?
按照一个属性排序
我们先看看按照一个字段排序的方式:
const person = [
{ name: '一', age: 30 },
{ name: '二', age: 18 },
{ name: '三', age: 6 },
{ name: '四', age: 63 },
{ name: '五', age: 35 }
]
person.sort((person, next) => person.age - next.age )
console.log('arrObject - 年龄正序 :\n', person)
按照年龄从小到大排序,看看结果:
person - 年龄正序 :
1. 1. 0: {name: "三", age: 6}
1. 1: {name: "二", age: 18}
1. 2: {name: "一", age: 30}
1. 3: {name: "五", age: 35}
1. 4: {name: "四", age: 63}
1. length: 5
1. __proto__: Array(0)
测试成功!
按照多个属性排序
那么能不能按照多个字段排序呢?
const person = [
{ name: '一', age: 30, score: 20 },
{ name: '二', age: 30, score: 24 },
{ name: '三', age: 6, score: 10 },
{ name: '四', age: 63, score: 220 },
{ name: '五', age: 35, score: 280 }
]
// 第一位扩大一千倍
const order = (person: any) => {
return person.age * 1000 + person.score
}
person.sort((person, next) => order(person) - order(next) )
console.log('arrObject - 先按年龄后按积分 :\n', person)
根据数值的范围,扩大第一位、第二位、第三位......,然后在做减法。
看看结果:
arrObject - 先按年龄后按积分 :
1. {name: "三", age: 6, score: 10}
1. 1: {name: "一", age: 30, score: 20}
1. 2: {name: "二", age: 30, score: 24}
1. 3: {name: "五", age: 35, score: 280}
1. 4: {name: "四", age: 63, score: 220}
这样不止是两个字段,多个字段也可以。
如果数值太大溢出怎么办?
那就先减再扩大:
const order2 = (person: any, next: any) => {
return (person.age - next.age) * 1000 + (person.score - next.score)
}
第一个字段升序,第二个字段降序咋办?
那就先减后加呗
const order3 = (person: any, next: any) => {
return (person.age - next.age) * 1000 + (-person.score + next.score)
}