如何比较两个版本号大小,如:1.2.4a和1.2.3b?

如题详述:

请用您熟悉的编程语言,编程实现一个比较任意两个软件版本号大小的函数,如 1.2.3a 和 1.2.4b 比较,后者版本号更大,请考虑各种情况,不可以使用系统提供的比较函数。

注:请问大家有没有好的实现方法与思路?

阅读 17.6k
7 个回答

常见的版本号命名方式,GNU,WINDOWS等,无外乎数字+字母,数字可能就是版本的迭代,如:V1.2.3, 也可能是日期,如V2018-06-25, 20180625。还有可能跟上阶段命名如 α β γ等。如果你只想比较数字部分,只需要去掉非数字部分,比较大小就行。
如果要比较字母部分,那要区分来看,对a b c这种,直接转成小写做大小比较就行。对trial, demo, unregistered这些,你要做个字典了。
如js代码

let version1 = 'v1.2.3a';
let version2 = 'v1.2.4b';
let versionNumber1 = version1.replace(/[a-zA-Z]/g, (match,i)=> match.charCodeAt()).replace(/[^\d]/g, '') - 0;
let versionNumber2 = version2.replace(/[a-zA-Z]/g, (match,i)=> match.charCodeAt()).replace(/[^\d]/g, '') - 0;
console.log(versionNumber1 > versionNumber2); 

以上代码面对 v1.2.97av1.10.1b 这样位数不一样的版本号可能有问题,特改进下,差异太大的就不行了,比如比较v2021333,v1.2.3

let version1 = 'v1.2.97a';
let version2 = 'v1.10.1b';
let versionArr1 = version1.replace(/[a-zA-Z]/g, (match,i)=> '.' + match.charCodeAt()).split(/[^\d]/);
let versionArr2 = version2.replace(/[a-zA-Z]/g, (match,i)=> '.' + match.charCodeAt()).split(/[^\d]/);

// 保证两个数据长度一样,面向 `v1.2` 和 `v1.2.3` 这样的情况
if(versionArr1.length > versionArr2.length) {
    versionArr2.splice(versionArr2.length, 0, ...Array(versionArr1.length-versionArr2.length).fill(0))
} else {
    versionArr1.splice(versionArr1.length, 0, ...Array(versionArr2.length-versionArr1.length).fill(0))
}

// 按节比较
let result = 'version1 equels version2.'
for(let i=0 ; i < versionArr1.length; i ++) {
    if (+versionArr1[i] > +versionArr2[i]) {
        result = 'version1 is bigger.';
        break;
    } else if (+versionArr1[i] < +versionArr2[i]){
        result = 'version2 is bigger.';
        break;
    } 
}
console.log(result);

按.分割,逐一对比

文档上大致写了version_compare的原理

clipboard.png

function compare(version1,version2){
            let arr1 = version1.split('.'); //版本1分割
            let arr2 = version2.split('.'); //版本2分割
            let [firstFlag,secondFlag,thirdFlag]=[false,false,false]; //定义版本的三个部分大小标志

            //1.判断第一位
            if( Number.parseInt(arr1[0]) > Number.parseInt(arr2[0]) ){
                firstFlag = true;
            }

            //2.判断第二位
            if( Number.parseInt(arr1[1]) > Number.parseInt(arr2[1]) ){
                secondFlag = true;
            }
                
            /*3.判断第三位
                1.全部为数字  
                2.全部为字母
                3.数字字母混合
            */
            //如果数组中第三个元素经过parseInt之后,得到的都不是NaN,说明都为数字
            if( Number(arr1[2]) && Number(arr2[2]) ){
                console.log('都为数字');
                thirdFlag = Number.parseInt(arr1[2]) > Number.parseInt(arr2[2]);
                //如果parseInt之后都为NaN,说明都是字母
            }else if( Number.isNaN(Number.parseInt(arr1[2])) && Number.isNaN(Number.parseInt(arr2[2])) ){
                console.log('都为字母');
                thirdFlag = arr1[2].charCodeAt() > arr2[2].charCodeAt();
            }else{
                console.log('字母和数字混合的');
                let num1 = Number.parseInt(arr1[2]);
                let num2 = Number.parseInt(arr2[2]);
                let word1 = arr1[2].split(num1)[1];
                let word2 = arr2[2].split(num2)[1];
                if(num1 > num2){
                    thirdFlag = true;
                }else{
                    thirdFlag = word1.charCodeAt() > word2.charCodeAt();
                }
            }
            return firstFlag || secondFlag || thirdFlag;
        }
新手上路,请多包涵

// 这个是小年糕公司的笔试题, 我做了这个题目获得了面试资格.去公司面试也是笔试,笔试挂掉了。
// 然后到公司是做这3个题目,https://www.cnblogs.com/mingz...

// 不考虑字母
function s2i(s) {
    return s.split('').reduce(function(a, c) {
        var code = c.charCodeAt(0);
        if (48<=code && code < 58) {
            a.push(code-48);
        }
        return a;
    }, []).reduce(function(a, c) {
        return 10*a + c;
    }, 0);
}
 
function versionCmp(s1, s2) {
    var a = s1.split('.').map(function(s) {
        return s2i(s);
    });
    var b = s2.split('.').map(function(s) {
        return s2i(s);
    });
    var n = a.length < b.length ? a.length : b.length;
    for (var i = 0; i < n; i++) {
        if (a[i] < b[i]) {
            return -1;
        } else if (a[i] > b[i]) {
            return 1;
        }
    }
    if (a.length < b.length) return -1;
    if (a.length > b.length) return 1;
    var last1 = s1.charCodeAt(s1.length-1) | 0x20,
        last2 = s2.charCodeAt(s2.length-1) | 0x20;
    return last1 > last2 ? 1 : last1 < last2 ? -1 : 0;
}

安利一个npm包

const semver = require('semver')

semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean('  =v1.2.3   ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题