以下是软件版本号:

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

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


当前回答

我也遇到过类似的问题,而且我已经为它创建了一个解决方案。你可以试一试。

如果等于则返回0,如果版本号大于则返回1,如果版本号小于则返回-1

function compareVersion(currentVersion, minVersion) { let current = currentVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10)) let min = minVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10)) for(let i = 0; i < Math.max(current.length, min.length); i++) { if((current[i] || 0) < (min[i] || 0)) { return -1 } else if ((current[i] || 0) > (min[i] || 0)) { return 1 } } return 0 } console.log(compareVersion("81.0.1212.121","80.4.1121.121")); console.log(compareVersion("81.0.1212.121","80.4.9921.121")); console.log(compareVersion("80.0.1212.121","80.4.9921.121")); console.log(compareVersion("4.4.0","4.4.1")); console.log(compareVersion("5.24","5.2")); console.log(compareVersion("4.1","4.1.2")); console.log(compareVersion("4.1.2","4.1")); console.log(compareVersion("4.4.4.4","4.4.4.4.4")); console.log(compareVersion("4.4.4.4.4.4","4.4.4.4.4")); console.log(compareVersion("0","1")); console.log(compareVersion("1","1")); console.log(compareVersion("1","1.0.00000.0000")); console.log(compareVersion("","1")); console.log(compareVersion("10.0.1","10.1"));

其他回答

2020年(大多数时候)正确的JavaScript答案

Nina Scholz在2020年3月和Sid Vishnoi在2020年4月都给出了现代的答案:

var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];

versions.sort((a, b) => 
   a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);

console.log(versions);

localCompare已经存在一段时间了

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator

但是1.0a和1.0.1呢

localCompare不能解决这个问题,仍然返回1.0.1,1.0a

迈克尔·迪尔(Michael Deal)在他的(略长且复杂的)解决方案中已经在2013年解决了这个问题

他将数字转换为另一种进位,以便更好地排序

他的回答让我思考……

666 -不要用数字思考- 999

排序是基于ASCII值的字母数字排序,所以让我们(ab)使用ASCII作为“基”

我的解决方案是将1.0.2.1到b.a.c.b转换为bacb,然后排序

这解决了1.1 vs. 1.0.0.0.1: bb vs. baaab

立即用baa和bab符号解决了1.0a和1.0.1排序问题

转换是通过:

    const str = s => s.match(/(\d+)|[a-z]/g)
                      .map(c => c == ~~c ? String.fromCharCode(97 + c) : c);

=计算ASCII值0…999数字,否则连字母

1.0 > > >(“0”,“1”” " ] >>> [ " b”、“”、“”)

为了便于比较,没有必要使用.join("")将其连接到一个字符串。

Oneliner

const sortVersions=(x,v=s=>s.match(/(\d+)|[a-z]/g)
                            .map(c=>c==~~c?String.fromCharCode(97+c):c))
                    =>x.sort((a,b)=>v(b)<v(a)?1:-1)

测试代码片段:

function log(label,val){ document.body.append(label,String(val).replace(/,/g," - "),document.createElement("BR")); } let v = ["1.90.1", "1.9.1", "1.89", "1.090", "1.2", "1.0a", "1.0.1", "1.10", "1.0.0a"]; log('not sorted input :',v); v.sort((a, b) => a.localeCompare(b,undefined,{numeric:true,sensitivity:'base' })); log(' locale Compare :', v); // 1.0a AFTER 1.0.1 const str = s => s.match(/(\d+)|[a-z]/g) .map(c => c == ~~c ? String.fromCharCode(97 + c) : c); const versionCompare = (a, b) => { a = str(a); b = str(b); return b < a ? 1 : a == b ? 0 : -1; } v.sort(versionCompare); log('versionCompare:', v);

注意1.090是如何在两个结果中排序的。

我的代码不会解决一个答案中提到的001.012.001符号,但是localeCompare正确地解决了这部分挑战。

你可以结合这两种方法:

当涉及字母时,使用.localCompare或versionCompare进行排序

最终的JavaScript解决方案

const sortVersions = ( x, V = s => s.match(/[a-z]|\d+/g)。Map (c => c==~~c ?String.fromCharCode(97 + c): c) => x.sort((a, b) => (a + b).match(/[a-z]/) ? V (b) < V (a) ?1: -1 : a.localeCompare(b, 0, {numeric: true})) 让v =[" 1.90.1”、“1.090”、“1.0”、“1.0.1”,“1.0.0a”,“1.0.0b”、“1.0.0.1”); console.log (sortVersions (v));

我想为解决这个问题的轻量级库做广告:语义版本

可以同时使用面向对象(OO)和面向函数。它可以作为npm-package和现成的包文件使用。

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

优点:

处理任意长度的版本字符串。'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

这个非常小,但非常快的比较函数接受每个段的任何长度和任何数字大小的版本号。

返回值: -如果a < b,则数字< 0 -如果是> b,则为> 0 如果a = b - 0

所以你可以使用它作为array。sort()的比较函数;

编辑:修正了版本剥离尾随零识别“1”和“1.0.0”相等的错误

function cmpVersions (a, b) { var i, diff; var regExStrip0 = /(\.0+)+$/; var segmentsA = a.replace(regExStrip0, '').split('.'); var segmentsB = b.replace(regExStrip0, '').split('.'); var l = Math.min(segmentsA.length, segmentsB.length); for (i = 0; i < l; i++) { diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10); if (diff) { return diff; } } return segmentsA.length - segmentsB.length; } // TEST console.log( ['2.5.10.4159', '1.0.0', '0.5', '0.4.1', '1', '1.1', '0.0.0', '2.5.0', '2', '0.0', '2.5.10', '10.5', '1.25.4', '1.2.15'].sort(cmpVersions)); // Result: // ["0.0.0", "0.0", "0.4.1", "0.5", "1.0.0", "1", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"]

我也遇到过类似的问题,而且我已经为它创建了一个解决方案。你可以试一试。

如果等于则返回0,如果版本号大于则返回1,如果版本号小于则返回-1

function compareVersion(currentVersion, minVersion) { let current = currentVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10)) let min = minVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10)) for(let i = 0; i < Math.max(current.length, min.length); i++) { if((current[i] || 0) < (min[i] || 0)) { return -1 } else if ((current[i] || 0) > (min[i] || 0)) { return 1 } } return 0 } console.log(compareVersion("81.0.1212.121","80.4.1121.121")); console.log(compareVersion("81.0.1212.121","80.4.9921.121")); console.log(compareVersion("80.0.1212.121","80.4.9921.121")); console.log(compareVersion("4.4.0","4.4.1")); console.log(compareVersion("5.24","5.2")); console.log(compareVersion("4.1","4.1.2")); console.log(compareVersion("4.1.2","4.1")); console.log(compareVersion("4.4.4.4","4.4.4.4.4")); console.log(compareVersion("4.4.4.4.4.4","4.4.4.4.4")); console.log(compareVersion("0","1")); console.log(compareVersion("1","1")); console.log(compareVersion("1","1.0.00000.0000")); console.log(compareVersion("","1")); console.log(compareVersion("10.0.1","10.1"));