我们开发的时候一定遇到过排序字符串的情况,一般来说,我们会使用比较操作符<,>,<=,>=或者localeCompare做字符串的比较,JavaScript解释器会把字符串转化成ASCII码逐个比较。但是我们也经常能遇到这种情况:
const arr = ['a1', 'a2', 'a1000']
arr.sort(function(a, b) { return a.localeCompare(b)})
// output ['a1', 'a1000', 'a2']
从程序的角度看,这是没有问题的,但这不太符合平时的习惯:
'a1' < 'a2' < 'a1000'
那么要怎样实现这样的排序,我们可以先利用正则表达式将字符串的数字和字母分开,然后组成数组
function splitStr(str) {
const arr = [];
str.replace(/\D|\d+/g, function (match) {
const val = +match;
arr.push(isNaN(val) ? match : val);
});
return arr;
}
splitStr('a100b01') // output: ['a', 100, 'b', 1]
然后我们再实现一个能比较这样数组的函数
function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
function descending(a, b) {
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}
function compare(a, b, comparator = ascending) {
const len = Math.min(a.length, b.length);
for (let i = 0; i < len; i++) {
const result = comparator(a[i], b[i]);
if (result !== 0) {
return result;
}
}
return comparator(a.length, b.length);
}
接下来我们就来实现这个排序的方法
function sort(arr, comparator) {
const newArr = arr.map((item) => splitStr(item));
let temp;
let len = newArr.length - 1;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i; j++) {
const result = compare(newArr[j], newArr[j + 1], comparator);
if (result > 0) {
temp = newArr[j];
newArr[j] = newArr[j + 1];
newArr[j + 1] = temp;
temp = arr[j]
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
const arr = ['a2', 'a1', 'a3', 'a1000', 'a201']
sort(arr);
console.log(arr) // ouput: [ 'a1', 'a2', 'a3', 'a201', 'a1000' ]