以下是软件版本号:

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

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


当前回答

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();

其他回答

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));

这适用于由句点分隔的任何长度的数字版本。只有当myVersion为>= minimumVersion时,它才返回true,假设版本1小于1.0,版本1.1小于1.1.0,以此类推。添加额外的条件应该相当简单,比如接受数字(只需转换为字符串)和十六进制,或者使分隔符动态(只需添加一个分隔符参数,然后将“。”替换为参数)

function versionCompare(myVersion, minimumVersion) {

    var v1 = myVersion.split("."), v2 = minimumVersion.split("."), minLength;   

    minLength= Math.min(v1.length, v2.length);

    for(i=0; i<minLength; i++) {
        if(Number(v1[i]) > Number(v2[i])) {
            return true;
        }
        if(Number(v1[i]) < Number(v2[i])) {
            return false;
        }           
    }

    return (v1.length >= v2.length);
}

下面是一些测试:

console.log(versionCompare("4.4.0","4.4.1"));
console.log(versionCompare("5.24","5.2"));
console.log(versionCompare("4.1","4.1.2"));
console.log(versionCompare("4.1.2","4.1"));
console.log(versionCompare("4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("4.4.4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("0","1"));
console.log(versionCompare("1","1"));
console.log(versionCompare("","1"));
console.log(versionCompare("10.0.1","10.1"));

这里有一个递归版本

function versionCompare(myVersion, minimumVersion) {
  return recursiveCompare(myVersion.split("."),minimumVersion.split("."),Math.min(myVersion.length, minimumVersion.length),0);
}

function recursiveCompare(v1, v2,minLength, index) {
  if(Number(v1[index]) < Number(v2[index])) {
    return false;
  }
  if(Number(v1[i]) < Number(v2[i])) {
    return true;
    }
  if(index === minLength) {
    return (v1.length >= v2.length);
  }
  return recursiveCompare(v1,v2,minLength,index+1);
}

基于Idan的精彩回答,下面的函数semverCompare通过了语义版本2.0.0的大多数情况。了解更多要点。

function semverCompare(a, b) {
    if (a.startsWith(b + "-")) return -1
    if (b.startsWith(a + "-")) return  1
    return a.localeCompare(b, undefined, { numeric: true, sensitivity: "case", caseFirst: "upper" })
}

它返回:

-1: a < b 0: a == b 1: a > b

摘自http://java.com/js/deployJava.js:

    // return true if 'installed' (considered as a JRE version string) is
    // greater than or equal to 'required' (again, a JRE version string).
    compareVersions: function (installed, required) {

        var a = installed.split('.');
        var b = required.split('.');

        for (var i = 0; i < a.length; ++i) {
            a[i] = Number(a[i]);
        }
        for (var i = 0; i < b.length; ++i) {
            b[i] = Number(b[i]);
        }
        if (a.length == 2) {
            a[2] = 0;
        }

        if (a[0] > b[0]) return true;
        if (a[0] < b[0]) return false;

        if (a[1] > b[1]) return true;
        if (a[1] < b[1]) return false;

        if (a[2] > b[2]) return true;
        if (a[2] < b[2]) return false;

        return true;
    }

我写了一个排序版本的节点模块,你可以在这里找到它:version-sort

特点:

序列“1.0.1.5.53.54654.114.1.154.45”不受限制 不限制序列长度:'1.1546515465451654654654654138754431574364321353734'工作 可以根据版本对对象进行排序(参见README) 阶段(如alpha, beta, rc1, rc2)

如果您需要其他功能,请不要犹豫,打开一个问题。