以下是软件版本号:

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

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


当前回答

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

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

其他回答

一个非常简单的方法:

function compareVer(previousVersion, currentVersion) {
 try {
    const [prevMajor, prevMinor = 0, prevPatch = 0] = previousVersion.split('.').map(Number);
    const [curMajor, curMinor = 0, curPatch = 0] = currentVersion.split('.').map(Number);

    if (curMajor > prevMajor) {
      return 'major update';
    }
    if (curMajor < prevMajor) {
      return 'major downgrade';
    }
    if (curMinor > prevMinor) {
      return 'minor update';
    }
    if (curMinor < prevMinor) {
      return 'minor downgrade';
    }
    if (curPatch > prevPatch) {
      return 'patch update';
    }
    if (curPatch < prevPatch) {
      return 'patch downgrade';
    }
    return 'same version';
  } catch (e) {
    return 'invalid format';
  }
}

输出:

compareVer("3.1", "3.1.1") // patch update
compareVer("3.1.1", "3.2") // minor update
compareVer("2.1.1", "1.1.1") // major downgrade
compareVer("1.1.1", "1.1.1") // same version

我喜欢@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;
     }
 }

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

函数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 } }

最简单的方法是使用localeCompare:

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

这将返回:

0:版本字符串相等 1: a版本大于b版本 -1:版本b大于版本a

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

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

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