【算法】版本号排序
对版本号数组进行排序,比如:[0.1.2.3,1.2.1.0,4.2.1.0,0.1.2.0]
核心思路
将版本号拆分为数字数组,逐个比较每个子版本段。具体步骤:
- 拆分版本号:将每个版本字符串按
.
分割成数字数组 - 逐位比较:从高位到低位依次比较每个子版本段
- 处理长度差异:短版本号的缺失部分视为
0
- 降序/升序控制:根据比较结果返回排序依据
代码实现
function sortVersions(versions) {return versions.sort((a, b) => {const partsA = a.split('.').map(Number); // 分割为数字数组 [0,1,2,3]const partsB = b.split('.').map(Number);const maxLen = Math.max(partsA.length, partsB.length); // 最长版本位数for (let i = 0; i < maxLen; i++) {const numA = partsA[i] || 0; // 超出长度部分补0const numB = partsB[i] || 0;if (numA !== numB) {return numB - numA; // 降序排列(修改为numA - numB则为升序)}}return 0; // 完全相等的情况});
}// 示例输入
const input = ['0.1.2.3', '1.2.1.0', '4.2.1.0', '0.1.2.0'];
console.log(sortVersions(input));
// 输出:[ '4.2.1.0', '1.2.1.0', '0.1.2.3', '0.1.2.0' ]
关键点解析
-
字符串转数字数组
split('.')
切割后通过map(Number)
转换为数值类型,避免字符串比较错误(如"10" < "2"
) -
补零处理长度差异
使用|| 0
处理长度不一致的版本号,如1.2
和1.2.0
视为相等 -
循环比较逻辑
逐位比较直到找到差异点,时间复杂度为 O(n)
应用场景优化
-
升序/降序切换
修改return numB - numA
为numA - numB
即可实现升序排列 -
处理长版本号
支持任意长度的版本号(如1.2.3.4.5.6
),最多可处理 10^3 量级的子版本号 -
特殊版本号扩展
• 预发布版本:拆分1.2.3-beta
为[1,2,3, 'beta']
,自定义非数字部分的排序规则• 语义化版本:优先比较主版本号(Major),其次次版本号(Minor),最后修订号(Patch)
性能对比
方法 | 时间复杂度 | 适用场景 | 缺陷 |
---|---|---|---|
字符串直接比较 | O(n log n) | 纯数字且子版本位宽相同 | 位宽不同时失效 |
大数加权法 | O(n log n) | 固定长度的语义化版本 | 数值溢出风险 |
逐位比较法 | O(n log n) | 任意长度的数字版本号 | 需处理类型转换 |
测试用例验证
// 测试案例
const testCases = [['1.10', '1.2'], // 1.10 > 1.2['2.5', '2.5.0'], // 相等['3.0.1', '3.0.0.9'], // 3.0.1 > 3.0.0.9['0.1', '0.0.9999'] // 0.1 > 0.0.9999
];
testCases.forEach(tc => console.log(sortVersions(tc)[0]));
// 输出均为第一个元素