以下是软件版本号:

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

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


当前回答

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

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

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

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

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

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

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

其他回答

这里找不到我想要的函数。所以我自己写了。这就是我的贡献。我希望有人觉得它有用。

优点:

处理任意长度的版本字符串。'1'或'1.1.1.1.1'。 如果没有指定,则默认为0。仅仅因为字符串更长并不意味着它是一个更大的版本。(“1”应与“1.0”和“1.0.0.0”相同。) 比较数字而不是字符串。('3'<'21'应为真。不是假的。) 不要把时间浪费在无用的比较上。(比较for ==) 你可以选择你自己的比较器。

缺点:

它不处理版本字符串中的字母。(我不知道这是怎么回事?)

我的代码,类似于Jon接受的答案:

function compareVersions(v1, comparator, v2) {
    "use strict";
    var comparator = comparator == '=' ? '==' : comparator;
    if(['==','===','<','<=','>','>=','!=','!=='].indexOf(comparator) == -1) {
        throw new Error('Invalid comparator. ' + comparator);
    }
    var v1parts = v1.split('.'), v2parts = v2.split('.');
    var maxLen = Math.max(v1parts.length, v2parts.length);
    var part1, part2;
    var cmp = 0;
    for(var i = 0; i < maxLen && !cmp; i++) {
        part1 = parseInt(v1parts[i], 10) || 0;
        part2 = parseInt(v2parts[i], 10) || 0;
        if(part1 < part2)
            cmp = 1;
        if(part1 > part2)
            cmp = -1;
    }
    return eval('0' + comparator + cmp);
}

例子:

compareVersions('1.2.0', '==', '1.2'); // true
compareVersions('00001', '==', '1.0.0'); // true
compareVersions('1.2.0', '<=', '1.2'); // true
compareVersions('2.2.0', '<=', '1.2'); // false

下面是另一个简短的版本,适用于任何数量的子版本,填充零和偶数字母(1.0.0b3)

const compareVer = ((prep, repl) =>
{
  prep = t => ("" + t)
      //treat non-numerical characters as lower version
      //replacing them with a negative number based on charcode of first character
    .replace(/[^0-9\.]+/g, c => "." + (c.replace(/[\W_]+/, "").toLowerCase().charCodeAt(0) - 65536) + ".")
      //remove trailing "." and "0" if followed by non-numerical characters (1.0.0b);
    .replace(/(?:\.0+)*(\.-[0-9]+)(\.[0-9]+)?\.*$/g, "$1$2")
    .split('.');

  return (a, b, c, i, r) =>
  {
    a = prep(a);
    b = prep(b);
    for (i = 0, r = 0, c = Math.max(a.length, b.length); !r && i++ < c;)
    {
      r = -1 * ((a[i] = ~~a[i]) < (b[i] = ~~b[i])) + (a[i] > b[i]);
    }
    return r;
  }
})();

函数返回:

如果a = b则为0

1如果a > b

-1如果a < b

1.0         = 1.0.0.0.0.0
1.0         < 1.0.1
1.0b1       < 1.0
1.0b        = 1.0b
1.1         > 1.0.1b
1.1alpha    < 1.1beta
1.1rc1      > 1.1beta
1.1rc1      < 1.1rc2
1.1.0a1     < 1.1a2
1.1.0a10    > 1.1.0a1
1.1.0alpha  = 1.1a
1.1.0alpha2 < 1.1b1
1.0001      > 1.00000.1.0.0.0.01

/*use strict*/ const compareVer = ((prep, repl) => { prep = t => ("" + t) //treat non-numerical characters as lower version //replacing them with a negative number based on charcode of first character .replace(/[^0-9\.]+/g, c => "." + (c.replace(/[\W_]+/, "").toLowerCase().charCodeAt(0) - 65536) + ".") //remove trailing "." and "0" if followed by non-numerical characters (1.0.0b); .replace(/(?:\.0+)*(\.-[0-9]+)(\.[0-9]+)?\.*$/g, "$1$2") .split('.'); return (a, b, c, i, r) => { a = prep(a); b = prep(b); for (i = 0, r = 0, c = Math.max(a.length, b.length); !r && i++ < c;) { r = -1 * ((a[i] = ~~a[i]) < (b[i] = ~~b[i])) + (a[i] > b[i]); } return r; } })(); //examples let list = [ ["1.0", "1.0.0.0.0.0"], ["1.0", "1.0.1"], ["1.0b1", "1.0"], ["1.0b", "1.0b"], ["1.1", "1.0.1b"], ["1.1alpha", "1.1beta"], ["1.1rc1", "1.1beta"], ["1.1rc1", "1.1rc2"], ["1.1.0a1", "1.1a2"], ["1.1.0a10", "1.1.0a1"], ["1.1.0alpha", "1.1a"], ["1.1.0alpha2", "1.1b1"], ["1.0001", "1.00000.1.0.0.0.01"] ] for(let i = 0; i < list.length; i++) { console.log( list[i][0] + " " + "<=>"[compareVer(list[i][0], list[i][1]) + 1] + " " + list[i][1] ); }

https://jsfiddle.net/vanowm/p7uvtbor/

检查php.js项目中的version_compare()函数。它类似于PHP的version_compare()。

你可以像这样简单地使用它:

version_compare('2.0', '2.0.0.1', '<'); 
// returns true

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

例如,如果我们想检查当前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/