媒介
头几天运用JavaScript中Array的sort排序字符串,发明排序不正确,这里记一下。
初版
var arr = ['0', '1', '11', '11', '2', '12', '123', '123', '333', '5'];
// 第一个版本
arr.sort(function(a, b) {
return a > b;
})
console.log(arr); // ['0', '1', '11', '11', '12', '123', '123', '2', '333', '5']
// 这里发明效果不对,料想的效果是 ['0', '1', '2', '5', '11', '11', '12', '123', '123', '333']
那就找缘由。发明的问题是字符串比较引发的。
在JavaScript中,字符串的比较,是字符按从左到右一一对应比较的。假如两个字符串第一个字符是一样,就比较第二个字符,假如第二个相称,就比较第三个,以此类推,直到比较出效果。
而单个字符间比较的划定规矩,这是是比较他们的charCode的大小。
列如:
'a'.charCodeAt(0) // 97
'b'.charCodeAt(0) // 98
'a' > 'b' // false
第二版
邃晓了字符串比较的划定规矩后, 就修改成下面的版本。
var arr = ['0', '1', '11', '11', '2', '12', '123', '123', '333', '5', '100'];
// 第二个版本
var isNumber = function(str) {
// 前面说了是字符串范例,所以这里没有做范例推断
return !isNaN(str);
}
// isNaN 这个要领须要注重, 会隐式的举行范例转, 须要注重
// isNaN(null) => false, isNaN(true) => false, isNaN([]) => false
arr.sort(function(a, b) {
// 假如比较两边都是number范例的字符,根据number举行比较
if(isNumber(a) && isNumber(b)) {
// 隐式转换
return a - b;
}
return a > b;
})
第三版
字符内里全都是数字是没有问题了,然则还须要斟酌非纯数字的状况
var arr = ['0', '1', '11', '11', '2', '12', '123', '123', '333', '5', 'aa', '1aa'];
// 从小到大
var isNumber = function(str) {
// 前面说了是字符串范例,所以这里没有做范例推断
return !isNaN(str);
}
arr.sort(function(a, b) {
// 假如比较两边都是number范例的字符,根据number举行比较
if(isNumber(a) && isNumber(b)) {
// 隐式转换
return a - b;
}
return a > b;
})
// 输出效果 ["0", "1", "2", "5", "11", "11", "12", "123", "123", "1aa", "333", "aa"] 这个没有问题的
// 从大到小
var arr = ['0', '1', '11', '11', '2', '12', '123', '123', '333', '5', 'aa', '1aa'];
var isNumber = function(str) {
// 前面说了是字符串范例,所以这里没有做范例推断
return !isNaN(str);
}
arr.sort(function(a, b) {
// 假如比较两边都是number范例的字符,根据number举行比较
if(isNumber(a) && isNumber(b)) {
// 隐式转换
return b - a;
}
return b > a;
})
// 输出效果 ["123", "1aa", "aa", "5", "2", "333", "123", "12", "11", "11", "1", "0"] 已经是不符合希冀
因而查找缘由,发明缘由是sort的比较要领的返回值不对。
假如想根据其他规范举行排序,就须要供应比较函数,该函数要比较两个值,然后返回一个用于申明这两个值的相对递次的数字。比较函数应当具有两个参数 a 和 b,其返回值以下:
若 a 小于 b,在排序后的数组中 a 应当出现在 b 之前,则返回一个小于 0 的值。
若 a 即是 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
而在第二版
的返回值是true与false,对应的是 1 和 0。因而修改成下面的版本
var arr = ['0', '1', '11', '11', '2', '12', '123', '123', '333', '5', 'aa', '1aa'];
// 从大到小
var isNumber = function(str) {
// 前面说了是字符串范例,所以这里没有做范例推断
return !isNaN(str);
}
arr.sort(function(a, b) {
// 假如比较两边都是number范例的字符,根据number举行比较
if(isNumber(a) && isNumber(b)) {
// 隐式转换
return b - a;
}
return b === a ? 0 : b > a ? 1 : -1;
})
// 输出效果["aa", "333", "1aa", "123", "123", "12", "11", "11", "5", "2", "1", "0"]
总结
在JS中字符串比较和sort举行排序不常常运用,运用的时刻多测测。就可以超出一些不必要的坑。