以下是软件版本号:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

我怎么比较呢?

假设正确的顺序是:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

想法很简单… 读第一个数字,然后,第二个,第三个… 但是我不能将版本号转换为浮点数… 你也可以像这样看到版本号:

"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"

这样可以更清楚地看到背后的想法。 但是,我怎样才能把它转换成计算机程序呢?


当前回答

这是另一种递归算法。

这段代码只使用了Array。shift和递归,这意味着它可以在Internet Explorer 6+中运行。如果你有任何疑问,你可以访问我的GitHub页面。

(function(root, factory) {
  if (typeof exports === 'object') {
    return module.exports = factory();
  } else if (typeof define === 'function' && define.amd) {
    return define(factory);
  } else {
    return root.compareVer = factory();
  }
})(this, function() {
  'use strict';
  var _compareVer;
  _compareVer = function(newVer, oldVer) {
    var VER_RE, compareNum, isTrue, maxLen, newArr, newLen, newMatch, oldArr, oldLen, oldMatch, zerofill;
    VER_RE = /(\d+\.){1,9}\d+/;
    if (arguments.length !== 2) {
      return -100;
    }
    if (typeof newVer !== 'string') {
      return -2;
    }
    if (typeof oldVer !== 'string') {
      return -3;
    }
    newMatch = newVer.match(VER_RE);
    if (!newMatch || newMatch[0] !== newVer) {
      return -4;
    }
    oldMatch = oldVer.match(VER_RE);
    if (!oldMatch || oldMatch[0] !== oldVer) {
      return -5;
    }
    newVer = newVer.replace(/^0/, '');
    oldVer = oldVer.replace(/^0/, '');
    if (newVer === oldVer) {
      return 0;
    } else {
      newArr = newVer.split('.');
      oldArr = oldVer.split('.');
      newLen = newArr.length;
      oldLen = oldArr.length;
      maxLen = Math.max(newLen, oldLen);
      zerofill = function() {
        newArr.length < maxLen && newArr.push('0');
        oldArr.length < maxLen && oldArr.push('0');
        return newArr.length !== oldArr.length && zerofill();
      };
      newLen !== oldLen && zerofill();
      if (newArr.toString() === oldArr.toString()) {
        if (newLen > oldLen) {
          return 1;
        } else {
          return -1;
        }
      } else {
        isTrue = -1;
        compareNum = function() {
          var _new, _old;
          _new = ~~newArr.shift();
          _old = ~~oldArr.shift();
          _new > _old && (isTrue = 1);
          return _new === _old && newArr.length > 0 && compareNum();
        };
        compareNum();
        return isTrue;
      }
    }
  };
  return _compareVer;
});

好吧,我希望这段代码能帮助到一些人。

下面是测试。

console.log(compareVer("0.0.2","0.0.1"));//1
console.log(compareVer("0.0.10","0.0.1")); //1
console.log(compareVer("0.0.10","0.0.2")); //1
console.log(compareVer("0.9.0","0.9")); //1
console.log(compareVer("0.10.0","0.9.0")); //1
console.log(compareVer("1.7", "1.07")); //1
console.log(compareVer("1.0.07", "1.0.007")); //1

console.log(compareVer("0.3","0.3")); //0
console.log(compareVer("0.0.3","0.0.3")); //0
console.log(compareVer("0.0.3.0","0.0.3.0")); //0
console.log(compareVer("00.3","0.3")); //0
console.log(compareVer("00.3","00.3")); //0
console.log(compareVer("01.0.3","1.0.3")); //0
console.log(compareVer("1.0.3","01.0.3")); //0

console.log(compareVer("0.2.0","1.0.0")); //-1
console.log(compareVer('0.0.2.2.0',"0.0.2.3")); //-1
console.log(compareVer('0.0.2.0',"0.0.2")); //-1
console.log(compareVer('0.0.2',"0.0.2.0")); //-1
console.log(compareVer("1.07", "1.7")); //-1
console.log(compareVer("1.0.007", "1.0.07")); //-1

console.log(compareVer()); //-100
console.log(compareVer("0.0.2")); //-100
console.log(compareVer("0.0.2","0.0.2","0.0.2")); //-100
console.log(compareVer(1212,"0.0.2")); //-2
console.log(compareVer("0.0.2",1212)); //-3
console.log(compareVer('1.abc.2',"1.0.2")); //-4
console.log(compareVer('1.0.2',"1.abc.2")); //-5

其他回答

这里有一个面向对象的有趣方法:

    function versionString(str) {
    var parts = str.split('.');
    this.product = parts.length > 0 ? parts[0] * 1 : 0;
    this.major = parts.length > 1 ? parts[1] * 1 : 0;
    this.minor = parts.length > 2 ? parts[2] * 1 : 0;
    this.build = parts.length > 3 ? parts[3] * 1 : 0;

    this.compareTo = function(vStr){
        vStr = this._isVersionString(vStr) ? vStr : new versionString(vStr);
        return this.compare(this, vStr);
    };

    this.toString = function(){
        return this.product + "." + this.major + "." + this.minor + "." + this.build;
    }

    this.compare = function (str1, str2) {
        var vs1 = this._isVersionString(str1) ? str1 : new versionString(str1);
        var vs2 = this._isVersionString(str2) ? str2 : new versionString(str2);

        if (this._compareNumbers(vs1.product, vs2.product) == 0) {
            if (this._compareNumbers(vs1.major, vs2.major) == 0) {
                if (this._compareNumbers(vs1.minor, vs2.minor) == 0) {
                    return this._compareNumbers(vs1.build, vs2.build);
                } else {
                    return this._compareNumbers(vs1.minor, vs2.minor);
                }
            } else {
                return this._compareNumbers(vs1.major, vs2.major);
            }
        } else {
            return this._compareNumbers(vs1.product, vs2.product);
        }
    };

    this._isVersionString = function (str) {
        return str !== undefined && str.build !== undefined;
    };

    this._compareNumbers = function (n1, n2) {
        if (n1 > n2) {
            return 1;
        } else if (n1 < n2) {
            return -1;
        } else {
            return 0;
        }
    };
}

还有一些测试:

var v1 = new versionString("1.0");
var v2 = new versionString("1.0.1");
var v3 = new versionString("2.0");
var v4 = new versionString("2.0.0.1");
var v5 = new versionString("2.0.1");


alert(v1.compareTo("1.4.2"));
alert(v3.compareTo(v1));
alert(v5.compareTo(v4));
alert(v4.compareTo(v5));
alert(v5.compareTo(v5));

我根据Kons的想法做了这个,并针对Java版本“1.7.0_45”进行了优化。它只是一个将版本字符串转换为浮点数的函数。这是函数:

function parseVersionFloat(versionString) {
    var versionArray = ("" + versionString)
            .replace("_", ".")
            .replace(/[^0-9.]/g, "")
            .split("."),
        sum = 0;
    for (var i = 0; i < versionArray.length; ++i) {
        sum += Number(versionArray[i]) / Math.pow(10, i * 3);
    }
    console.log(versionString + " -> " + sum);
    return sum;
}

字符串“1.7.0_45”被转换为1.0070000450000001,这足以进行正常的比较。这里解释的错误:如何处理JavaScript中的浮点数精度?如果需要超过3个数字在任何部分,你可以改变除法数学。Pow (10, I * 3);;

输出如下所示:

1.7.0_45         > 1.007000045
ver 1.7.build_45 > 1.007000045
1.234.567.890    > 1.23456789

replace()函数只替换字符串中的第一个出现项。我们来替换。与,。然后全部删除。然后做,to。再次将其解析为float。

for(i=0; i<versions.length; i++) {
    v = versions[i].replace('.', ',');
    v = v.replace(/\./g, '');
    versions[i] = parseFloat(v.replace(',', '.'));
}

最后,排序:

versions.sort();

这实际上取决于版本控制系统背后的逻辑。每个数字代表什么,如何使用。

每个subversion是否是一个用于指定开发阶段的数字? 为0 1代表β 发布候选2个 3为(最终)发布

它是构建版本吗?您是否应用增量更新?

一旦了解了版本控制系统的工作原理,创建算法就变得很容易了。

如果您不允许在每个subversion中使用大于9的数字,则删除所有小数,但第一个小数将允许您进行直接比较。

如果允许在任何一种颠覆版本中使用大于9的数字,有几种方法可以比较它们。最明显的方法是将字符串按小数分割,然后比较每一列。

但是在不知道版本控制系统是如何工作的情况下,当版本1.0.2a发布时,实现像上面这样的过程可能会很麻烦。

把它转换成一个数字,然后比较。 假设每个主要/次要/补丁使用不超过3个数字,并且没有标签 (像这个1.12.042)

const versionNumber = +versionString
  .split('.')
  .map(v => '000' + v)
  .map(v => v.slice(-3))
  .join('');