在力扣上有一道经典的笔试题,比较两个版本号的大小,通常的解决思路就是将版本号拆分,然后逐个比较,最后写出来大概是下面这个鬼样子,虽然看起来没毛病,运行起来也没问题,但是就是不够骚气
function isVersionGreaterThan(version1: string, version2: string): boolean {
// 分割版本号为各个部分
const v1Parts: number[] = version1.split('.').map(Number);
const v2Parts: number[] = version2.split('.').map(Number);
// 获取版本号的长度
const lenV1: number = v1Parts.length;
const lenV2: number = v2Parts.length;
// 循环比较各个部分
for (let i = 0; i < Math.max(lenV1, lenV2); i++) {
const v1Part: number = i < lenV1 ? v1Parts[i] : 0;
const v2Part: number = i < lenV2 ? v2Parts[i] : 0;
if (v1Part < v2Part) {
return false;
} else if (v1Part > v2Part) {
return true;
}
}
// 如果所有部分都相等,则版本号相等,此时也返回 false
return false;
}
// 测试
const version1: string = "1.2.3";
const version2: string = "1.2.4";
const result: boolean = isVersionGreaterThan(version1, version2); console.log(result); // 输出 false
最近发现一个很骚的写法,思路也很惊奇。比较版本号通常是逐位比较,如果当前位的版本已经能比较出大小了,则可以直接返回比较结果,否则继续比较下一位直到遍历完所有位数。但是呢这太常规了,代码写得不骚气,如何才能涨薪呢,那怎么才能唬住接手的同事呢。下面这种方法,不需要使用循环遍历版本的每一位,通过生成器,每次迭代出一位版本号,然后比较。一个字
绝!
function* walk(version: string) {
let part = '';
const delimiter = ['.', '-'];
for (let i = 0; i < version.length; i++) {
const char = version[i];
if (delimiter.includes(char)) {
yield part;
part = '';
} else {
part += char;
}
}
}
/**
* 比较两个版本号
* - v1 大于 v2 返回 `true`
* - v1 小于等于 v2 返回 `false`
* @param v1
* @param v2
* @returns boolean
*/
function compareVersion(v1: string, v2: string): boolean {
const g1 = walk(v1);
const g2 = walk(v2);
while (true) {
const n1 = g1.next();
const n2 = g2.next();
if (n1.value > n2.value) {
return true;
}
if (n1.value < n2.value) {
return false;
}
if (n1.done === n2.done && n1.done === true) {
return false;
}
}
}
const v1 = '12.4.2';
const v2 = '12.4.1';
console.log(compareVersion(v1, v2)); // true