以下是软件版本号:

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

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


当前回答

你可以使用JavaScript的localeCompare方法:

a.localeCompare(b, undefined, {numeric: true})

这里有一个例子:

"1.1".localeCompare("2.1.1", undefined, {numeric: true}) => -1

"1.0.0".localeCompare("1.0", undefined, {numeric: true}) =>

"1.0.0".localeCompare("1.0.0", undefined, {numeric: true}) => 0

其他回答

例如,如果我们想检查当前jQuery版本是否小于1.8,如果version是"1.10.1",parseFloat($.ui.version) < 1.8)将会给出错误的结果,因为parseFloat("1.10.1")返回1.1。 字符串比较也会出错,因为"1.8" < "1.10"的结果为false。

所以我们需要一个这样的测试

if(versionCompare($.ui.version, "1.8") < 0){
    alert("please update jQuery");
}

下面的函数可以正确地处理这个问题:

/** Compare two dotted version strings (like '10.2.3').
 * @returns {Integer} 0: v1 == v2, -1: v1 < v2, 1: v1 > v2
 */
function versionCompare(v1, v2) {
    var v1parts = ("" + v1).split("."),
        v2parts = ("" + v2).split("."),
        minLength = Math.min(v1parts.length, v2parts.length),
        p1, p2, i;
    // Compare tuple pair-by-pair. 
    for(i = 0; i < minLength; i++) {
        // Convert to integer if possible, because "8" > "10".
        p1 = parseInt(v1parts[i], 10);
        p2 = parseInt(v2parts[i], 10);
        if (isNaN(p1)){ p1 = v1parts[i]; } 
        if (isNaN(p2)){ p2 = v2parts[i]; } 
        if (p1 == p2) {
            continue;
        }else if (p1 > p2) {
            return 1;
        }else if (p1 < p2) {
            return -1;
        }
        // one operand is NaN
        return NaN;
    }
    // The longer tuple is always considered 'greater'
    if (v1parts.length === v2parts.length) {
        return 0;
    }
    return (v1parts.length < v2parts.length) ? -1 : 1;
}

下面是一些例子:

// compare dotted version strings
console.assert(versionCompare("1.8",      "1.8.1")    <   0);
console.assert(versionCompare("1.8.3",    "1.8.1")    >   0);
console.assert(versionCompare("1.8",      "1.10")     <   0);
console.assert(versionCompare("1.10.1",   "1.10.1")   === 0);
// Longer is considered 'greater'
console.assert(versionCompare("1.10.1.0", "1.10.1")   >   0);
console.assert(versionCompare("1.10.1",   "1.10.1.0") <   0);
// Strings pairs are accepted
console.assert(versionCompare("1.x",      "1.x")      === 0);
// Mixed int/string pairs return NaN
console.assert(isNaN(versionCompare("1.8", "1.x")));
//works with plain numbers
console.assert(versionCompare("4", 3)   >   0);

看到这里的现场示例和测试套件: http://jsfiddle.net/mar10/8KjvP/

功能简单简短:

function isNewerVersion (oldVer, newVer) {
  const oldParts = oldVer.split('.')
  const newParts = newVer.split('.')
  for (var i = 0; i < newParts.length; i++) {
    const a = ~~newParts[i] // parse int
    const b = ~~oldParts[i] // parse int
    if (a > b) return true
    if (a < b) return false
  }
  return false
}

测试:

isNewerVersion('1.0', '2.0') // true
isNewerVersion('1.0', '1.0.1') // true
isNewerVersion('1.0.1', '1.0.10') // true
isNewerVersion('1.0.1', '1.0.1') // false
isNewerVersion('2.0', '1.0') // false
isNewerVersion('2', '1.0') // false
isNewerVersion('2.0.0.0.0.1', '2.1') // true
isNewerVersion('2.0.0.0.0.1', '2.0') // false

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

你可以遍历每个以句点分隔的字符并将其转换为int类型:

var parts = versionString.split('.');

for (var i = 0; i < parts.length; i++) {
  var value = parseInt(parts[i]);
  // do stuffs here.. perhaps build a numeric version variable?
}

在排序之前对版本进行预处理意味着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"