以下是软件版本号:

"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"

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


当前回答

我根据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

其他回答

我也遇到了版本比较的问题,但是版本可能包含任何内容(例如:不是点的分隔符,像rc1, rc2…)

我使用了这个方法,它基本上将版本字符串分为数字和非数字,并尝试根据类型进行比较。

function versionCompare(a,b) {
  av = a.match(/([0-9]+|[^0-9]+)/g)
  bv = b.match(/([0-9]+|[^0-9]+)/g)
  for (;;) {
    ia = av.shift();
    ib = bv.shift();
    if ( (typeof ia === 'undefined') && (typeof ib === 'undefined') ) { return 0; }
    if (typeof ia === 'undefined') { ia = '' }
    if (typeof ib === 'undefined') { ib = '' }

    ian = parseInt(ia);
    ibn = parseInt(ib);
    if ( isNaN(ian) || isNaN(ibn) ) {
      // non-numeric comparison
      if (ia < ib) { return -1;}
      if (ia > ib) { return 1;}
    } else {
      if (ian < ibn) { return -1;}
      if (ian > ibn) { return 1;}
    }
  }
}

对于某些情况,这里有一些假设,例如:"1.01" === "1.1",或"1.8" < "1.71"。它无法管理“1.0.0-rc”。1" < "1.0.0",由语义版本2.0.0指定

我的答案比这里的大多数答案都要简洁

/**
 * Compare two semver versions. Returns true if version A is greater than
 * version B
 * @param {string} versionA
 * @param {string} versionB
 * @returns {boolean}
 */
export const semverGreaterThan = function(versionA, versionB){
  var versionsA = versionA.split(/\./g),
    versionsB = versionB.split(/\./g)
  while (versionsA.length || versionsB.length) {
    var a = Number(versionsA.shift()), b = Number(versionsB.shift())
    if (a == b)
      continue
    return (a > b || isNaN(b))
  }
  return false
}

如果不允许使用字母或符号,那么代码行数就很少。如果您控制了版本控制方案,并且不是第三方提供的,那么这种方法是有效的。

// we presume all versions are of this format "1.4" or "1.10.2.3", without letters // returns: 1 (bigger), 0 (same), -1 (smaller) function versionCompare (v1, v2) { const v1Parts = v1.split('.') const v2Parts = v2.split('.') const length = Math.max(v1Parts.length, v2Parts.length) for (let i = 0; i < length; i++) { const value = (parseInt(v1Parts[i]) || 0) - (parseInt(v2Parts[i]) || 0) if (value < 0) return -1 if (value > 0) return 1 } return 0 } console.log(versionCompare('1.2.0', '1.2.4') === -1) console.log(versionCompare('1.2', '1.2.0') === 0) console.log(versionCompare('1.2', '1') === 1) console.log(versionCompare('1.2.10', '1.2.1') === 1) console.log(versionCompare('1.2.134230', '1.2.2') === 1) console.log(versionCompare('1.2.134230', '1.3.0.1.2.3.1') === -1)

在排序之前对版本进行预处理意味着parseInt不会被不必要地多次调用。 使用array# map类似于Michael Deal的建议,下面是我用来查找标准3部分semver的最新版本的排序:

var semvers = ["0.1.0", "1.0.0", "1.1.0", "1.0.5"]; var versions = semvers.map(function(semver) { return semver.split(".").map(function(part) { return parseInt(part); }); }); versions.sort(function(a, b) { if (a[0] < b[0]) return 1; else if (a[0] > b[0]) return -1; else if (a[1] < b[1]) return 1; else if (a[1] > b[1]) return -1; else if (a[2] < b[2]) return 1; else if (a[2] > b[2]) return -1; return 0; }); var newest = versions[0].join("."); console.log(newest); // "1.1.0"

现在我们可以使用Intl了。Collator API现在创建数值比较器。浏览器支持是相当不错的,但在撰写本文时,Node.js还不支持。

const semverCompare = new Intl。Collator("en", {numeric: true}).compare; const版本=[1.0.1,“1.10.2”,“1.1.1”,‘1.10.1’,‘1.5.10’,‘2.10.0’,‘2.0.1’); console.log (versions.sort (semverCompare)) const example2 =(“1.0”,“1.0.1”,“2.0”,“2.0.0.1”,“2.0.1”); console.log (example2.sort (semverCompare))