数字版本号排序,非数字排序
4种排序函数以及耗时
- 2、3方式,循环比较
- 1 方式,转数据类型节省sort里面的循环比较(直接比较)
- 4 方式,转数据类型后采用桶排序节省大部分Array.sort排序的时间(数据量庞大时优势明显)
- 不限制排序的数据格式,只需要转为对应的数字
- 易重写
/**
* 桶排序
* @param {Array<object>} arr 数组
* @param {function(object): number} build 项构造器,返回数字
*/
function bucketSorting(arr, build) {
const numbers = arr.map(build), list = new Array(Math.floor(arr.length / 2)), result = [];
let min = numbers[0], max = numbers[0], c = 0;
while (++c < numbers.length) {
if (numbers[c] < min) {
min = numbers[c];
}
if (numbers[c] > max) {
max = numbers[c];
}
}
for (let i = 0; i < list.length; i++) {
list[i] = [];
}
const difference = max - min;
c = -1;
while (++c < numbers.length) {
const n = numbers[c];
list[Math.floor((n - min) / difference * (list.length - 1))].push(c);
}
list.map(e => e.sort((a, b) => numbers[a] - numbers[b])).forEach(e => (e || []).forEach(a => result.push(numbers[a])));
return result;
}
- 采用 转数据类型+排序
/**
* 只要不是1.1.1.1.1....这种点点特多的情况,完全可以忽略精度问题。
* @param {Array<string>} versions
*/
function versionSort(versions = []) {
return versions.map((b, index) => {
return {
number: b.split(".").map((c, i) => +("0." + c) * Math.pow(10, 5 - i)).reduce((b, c) => b + c),
value: b
}
}).sort((b, c) => b.number - c.number).map(e => e.value);
}
- 采用 排序+循环
/**
* @param {Array<String>} versions
*/
function versionSortLoop(versions = []) {
return versions.sort((a, b) => {
const _a = a.split(".").map(e => +e);
const _b = b.split(".").map(e => +e);
while (_a.length > 0) {
const fisrt = _a.shift();
const two = _b.shift() || 0;
if (fisrt > two) {
return 1;
} else if (fisrt < two) {
return -1;
}
}
return 0;
});
}
- 采用
百度方式
function sortVersion(list) {
return list.sort((version1, version2) => {
const arr1 = version1.split('.').map(e => e * 1)
const arr2 = version2.split('.').map(e => e * 1)
const length = Math.max(arr1.length, arr2.length)
for (let i = 0; i < length; i++) {
if ((arr1[i] || 0) > (arr2[i] || 0)) return 1
if ((arr1[i] || 0) < (arr2[i] || 0)) return -1
}
return 0
})
}
- 采用桶排序+转数据类型+sort排序
function versionSortBucket(versions = []) {
return bucketSorting(versions.map((b, index) => {
return {
number: b.split(".").map((c, i) => +("0." + c) * Math.pow(10, 5 - i)).reduce((b, c) => b + c),
value: b
}
}), (e) => e.number).map(e => e.value);
}
class Log {
run(func, title) {
console.log("------------" + title + "------------");
func();
console.log("------------------------");
}
static runTime(func) {
const beginTime = new Date();
func();
const endTime = new Date();
const consume = endTime - beginTime;
return consume;
}
}
const log = new Log();
const a = ['0.1.1', '0.1.0.1', '2.3.3', '0.3002.1', '4.2', '4.2.1', '4.3.5', '4.3.5.1', '4.3.4.5'];
const a1 = ['0.1.1', '0.1.0.1', '2.3.3', '0.3002.1', '4.2', '4.2.1', '4.3.5', '4.3.5.1', '4.3.4.5'];
let c;
c = 1000;
while (--c > 0) {
a1.push([Math.random(), Math.random(), Math.random()].join("."));
}
c = 20;
log.run(() => {
while (--c >= 0) {
console.log(`第${20 - c}次测试:\tversionSortLoop\t${Log.runTime(() => versionSortLoop(a1))}ms\tversionSort\t${Log.runTime(() => versionSort(a1))}ms\tsortVersion\t${Log.runTime(() => sortVersion(a1))}ms`);
}
}, "少数据测试," + a1.length);
c = 10000;
while (--c > 0) {
a.push([Math.random(), Math.random(), Math.random()].join("."));
}
c = 20;
log.run(() => {
while (--c >= 0) {
console.log(`第${20 - c}次测试:\tversionSortLoop\t${Log.runTime(() => versionSortLoop(a))}ms\tversionSort\t${Log.runTime(() => versionSort(a))}ms\tsortVersion\t${Log.runTime(() => sortVersion(a))}ms`);
}
}, "多数据测试," + a.length);