以下是软件版本号:

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

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


当前回答

const compareAppVersions = (firstVersion, secondVersion) => { const firstVersionArray = firstVersion.split(".").map(Number); const secondVersionArray = secondVersion.split(".").map(Number); const loopLength = Math.max( firstVersionArray.length, secondVersionArray.length ); 对于(设I = 0;i < loopLength;+ + i) { const a = firstVersionArray[i] || 0; const b = secondVersionArray[i] || 0; If (a !== b) { 返回> b ?1: -1; } } 返回0; };

其他回答

我喜欢@mar10的版本,尽管从我的角度来看,有误用的可能(如果版本与Semantic Versioning文档兼容,似乎不是这样,但如果使用了一些“构建号”,则可能是这样):

versionCompare( '1.09', '1.1');  // returns 1, which is wrong:  1.09 < 1.1
versionCompare('1.702', '1.8');  // returns 1, which is wrong: 1.702 < 1.8

这里的问题是,在某些情况下,版本号的子数字被删除了后面的零(至少我最近在使用不同的软件时看到的),这类似于数字的有理数部分,因此:

5.17.2054 > 5.17.2
5.17.2 == 5.17.20 == 5.17.200 == ... 
5.17.2054 > 5.17.20
5.17.2054 > 5.17.200
5.17.2054 > 5.17.2000
5.17.2054 > 5.17.20000
5.17.2054 < 5.17.20001
5.17.2054 < 5.17.3
5.17.2054 < 5.17.30

但是,第一个(或第一个和第二个)版本子号始终被视为它实际等于的整数值。

如果你使用这种版本控制,你可以只改变例子中的几行:

// replace this:
p1 = parseInt(v1parts[i], 10);
p2 = parseInt(v2parts[i], 10);
// with this:
p1 = i/* > 0 */ ? parseFloat('0.' + v1parts[i], 10) : parseInt(v1parts[i], 10);
p2 = i/* > 0 */ ? parseFloat('0.' + v2parts[i], 10) : parseInt(v2parts[i], 10);

因此,除了第一个子数字外,每个子数字都将作为浮点数进行比较,因此09和1将相应地变成0.09和0.1,并以这种方式进行正确比较。2054和3将变成0.2054和0.3。

那么,完整的版本是(归功于@mar10):

/** 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 = i/* > 0 */ ? parseFloat('0.' + v1parts[i], 10) : parseInt(v1parts[i], 10);;
        p2 = i/* > 0 */ ? parseFloat('0.' + v2parts[i], 10) : 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;
}

注:这是比较慢的,但也可以考虑重用相同的比较函数来操作字符串实际上是字符数组的事实:

 function cmp_ver(arr1, arr2) {
     // fill the tail of the array with smaller length with zeroes, to make both array have the same length
     while (min_arr.length < max_arr.length) {
         min_arr[min_arr.lentgh] = '0';
     }
     // compare every element in arr1 with corresponding element from arr2, 
     // but pass them into the same function, so string '2054' will act as
     // ['2','0','5','4'] and string '19', in this case, will become ['1', '9', '0', '0']
     for (i: 0 -> max_length) {
         var res = cmp_ver(arr1[i], arr2[i]);
         if (res !== 0) return res;
     }
 }

现在我们可以使用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))

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

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

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

特点:

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

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

如果数组包含数字,则可以对数组进行比较。 转换为没有点的数组并比较它们。

函数VersionCompare(version1, version2){ var regExStrip0 = /(\.0+)+$/; var segmentsA = version1。替换(regExStrip0”).split (' . '); var segmentsB = version2。替换(regExStrip0”).split (' . '); if(segmentsA > segmentsB){ 返回1 }else if (segmentsA< segmentsB){ 返回1 其他}{ 返回0 } }