How can I compare software version number using JavaScript? (only numbers)

Viewed 133328

Here is the software version number:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

How can I compare this?

Assume the correct order is:

"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"

The idea is simple...: Read the first digit, than, the second, after that the third... But I can't convert the version number to float number... You also can see the version number like this:

"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"

And this is clearer to see what is the idea behind... But, how can I convert it into a computer program?

56 Answers

The simplest is to use localeCompare :

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

This will return:

  • 0: version strings are equal
  • 1: version a is greater than b
  • -1: version b is greater than a

Simple and short function:

function isNewerVersion (oldVer, newVer) {
  const oldParts = oldVer.split('.')
  const newParts = newVer.split('.')
  for (var i = 0; i < newParts.length; i++) {
    const a = ~~newParts[i] // parse int
    const b = ~~oldParts[i] // parse int
    if (a > b) return true
    if (a < b) return false
  }
  return false
}

Tests:

isNewerVersion('1.0', '2.0') // true
isNewerVersion('1.0', '1.0.1') // true
isNewerVersion('1.0.1', '1.0.10') // true
isNewerVersion('1.0.1', '1.0.1') // false
isNewerVersion('2.0', '1.0') // false
isNewerVersion('2', '1.0') // false
isNewerVersion('2.0.0.0.0.1', '2.1') // true
isNewerVersion('2.0.0.0.0.1', '2.0') // false

Couldn't find a function doing what I wanted here. So I wrote my own. This is my contribution. I hope someone find it useful.

Pros:

  • Handles version strings of arbitrary length. '1' or '1.1.1.1.1'.

  • Defaults each value to 0 if not specified. Just because a string is longer doesn't mean it's a bigger version. ('1' should be the same as '1.0' and '1.0.0.0'.)

  • Compare numbers not strings. ('3'<'21' should be true. Not false.)

  • Don't waste time on useless compares in the loop. (Comparing for ==)

  • You can choose your own comparator.

Cons:

  • It does not handle letters in the version string. (I don't know how that would even work?)

My code, similar to the accepted answer by 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);
}

Examples:

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

Here is another short version that works with any number of sub versions, padded zeros and even numbers with letters (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;
  }
})();

Function returns:

0 if a = b

1 if a > b

-1 if 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/

2017 answer:

v1 = '20.0.12'; 
v2 = '3.123.12';

compareVersions(v1,v2) 
// return positive: v1 > v2, zero:v1 == v2, negative: v1 < v2 
function compareVersions(v1, v2) {
        v1= v1.split('.')
        v2= v2.split('.')
        var len = Math.max(v1.length,v2.length)
        /*default is true*/
        for( let i=0; i < len; i++)
            v1 = Number(v1[i] || 0);
            v2 = Number(v2[i] || 0);
            if (v1 !== v2) return v1 - v2 ;
            i++;
        }
        return 0;
    }

Simplest code for modern browsers:

 function compareVersion2(ver1, ver2) {
      ver1 = ver1.split('.').map( s => s.padStart(10) ).join('.');
      ver2 = ver2.split('.').map( s => s.padStart(10) ).join('.');
      return ver1 <= ver2;
 }

The idea here is to compare numbers but in the form of string. to make the comparison work the two strings must be at the same length. so:

"123" > "99" become "123" > "099"
padding the short number "fix" the comparison

Here I padding each part with zeros to lengths of 10. then just use simple string compare for the answer

Example :

var ver1 = '0.2.10', ver2=`0.10.2`
//become 
ver1 = '0000000000.0000000002.0000000010'
ver2 = '0000000000.0000000010.0000000002'
// then it easy to see that
ver1 <= ver2 // true

Although this question already has a lot of answers, each one promotes their own backyard-brewn solution, whilst we have a whole ecosystem of (battle-)tested libraries for this.

A quick search on NPM, GitHub, X will give us some lovely libs, and I'd want to run through some:

semver-compare is a great lightweight (~230 bytes) lib that's especially useful if you want to sort by version numbers, as the library's exposed method returns -1, 0 or 1 appropriately.

The core of the library:

module.exports = function cmp (a, b) {
    var pa = a.split('.');
    var pb = b.split('.');
    for (var i = 0; i < 3; i++) {
        var na = Number(pa[i]);
        var nb = Number(pb[i]);
        if (na > nb) return 1;
        if (nb > na) return -1;
        if (!isNaN(na) && isNaN(nb)) return 1;
        if (isNaN(na) && !isNaN(nb)) return -1;
    }
    return 0;
};

compare-semver is rather hefty in size (~4.4 kB gzipped), but allows for some nice unique comparisons like to find the minimum/maximum of a stack of versions or to find out if the provided version is unique or less than anything else in a collection of versions.

compare-versions is another small library (~630 bytes gzipped) and follows the spec nicely, meaning you can compare versions with alpha/beta flags and even wildcards (like for minor/patch versions: 1.0.x or 1.0.*)

The point being: there's not always a need to copy-paste code from Stack Overflow, if you can find decent, (unit-)tested versions via your package manager of choice.

I faced the similar issue, and I had already created a solution for it. Feel free to give it a try.

It returns 0 for equal, 1 if the version is greater and -1 if it is less

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

A dead simple way:

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';
  }
}

Output:

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

My less verbose answer than most of the answers here

/**
 * Compare two semver versions. Returns true if version A is greater than
 * version B
 * @param {string} versionA
 * @param {string} versionB
 * @returns {boolean}
 */
export const semverGreaterThan = function(versionA, versionB){
  var versionsA = versionA.split(/\./g),
    versionsB = versionB.split(/\./g)
  while (versionsA.length || versionsB.length) {
    var a = Number(versionsA.shift()), b = Number(versionsB.shift())
    if (a == b)
      continue
    return (a > b || isNaN(b))
  }
  return false
}

You could use String#localeCompare with options

sensitivity

Which differences in the strings should lead to non-zero result values. Possible values are:

  • "base": Only strings that differ in base letters compare as unequal. Examples: a ≠ b, a = á, a = A.
  • "accent": Only strings that differ in base letters or accents and other diacritic marks compare as unequal. Examples: a ≠ b, a ≠ á, a = A.
  • "case": Only strings that differ in base letters or case compare as unequal. Examples: a ≠ b, a = á, a ≠ A.
  • "variant": Strings that differ in base letters, accents and other diacritic marks, or case compare as unequal. Other differences may also be taken into consideration. Examples: a ≠ b, a ≠ á, a ≠ A.

The default is "variant" for usage "sort"; it's locale dependent for usage "search".

numeric

Whether numeric collation should be used, such that "1" < "2" < "10". Possible values are true and false; the default is false. This option can be set through an options property or through a Unicode extension key; if both are provided, the options property takes precedence. Implementations are not required to support this property.

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

The (most of the time) correct JavaScript answer in 2020

Both Nina Scholz in March 2020 and Sid Vishnoi in April 2020 post the modern answer:

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 has been around for some time

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

But what about 1.0a and 1.0.1

localCompare doesn't solve that, still returns 1.0.1 , 1.0a

Michael Deal in his (longish &complex) solution already cracked that in 2013

He converts Numbers to another Base, so they can be sorted better

His answer got me thinking...

666 - Don't think in numbers - 999

Sorting is alphanumeric, based on the ASCII values, so let's (ab)use ASCII as the "base"

My solution is to convert 1.0.2.1 to b.a.c.b to bacb , and then sort

This solves 1.1 vs. 1.0.0.0.1 with: bb vs. baaab

And immediately solves the 1.0a and 1.0.1 sorting problem with notation: baa and bab

Conversion is done with:

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

= Calculate ASCII value for 0...999 Numbers, otherwise concat letter

1.0a >>> [ "1" , "0" , "a" ] >>> [ "b" , "a" , "a" ]

For comparison sake there is no need to concatenate it to one string with .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)

Test snippet:

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

Note how 1.090 is sorted in both results.

My code will not solve the 001.012.001 notation mentioned in one answer, but the localeCompare gets that part of the challenge right.

You could combine the two methods:

  • sort with .localCompare OR versionCompare when there is a letter involved

Final JavaScript solution

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

let v=["1.90.1","1.090","1.0a","1.0.1","1.0.0a","1.0.0b","1.0.0.1"];
console.log(sortVersions(v));

We can now use Intl.Collator API now to create numeric comparators. Browser support is pretty decent, but not supported in Node.js at the time of writing.

const semverCompare = new Intl.Collator("en", { numeric: true }).compare;

const versions = ['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))

Few lines of code and good if you don't want to allow letters or symbols. This works if you control the versioning scheme and it's not something a 3rd party provides.

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

You can use a JavaScript localeCompare method:

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

Here is an example:

"1.1".localeCompare("2.1.1", undefined, { numeric: true }) => -1

"1.0.0".localeCompare("1.0", undefined, { numeric: true }) => 1

"1.0.0".localeCompare("1.0.0", undefined, { numeric: true }) => 0

// Returns true if v1 is bigger than v2, and false if otherwise.
function isNewerThan(v1, v2) {
      v1=v1.split('.');
      v2=v2.split('.');
      for(var i = 0; i<Math.max(v1.length,v2.length); i++){
        if(v1[i] == undefined) return false; // If there is no digit, v2 is automatically bigger
        if(v2[i] == undefined) return true; // if there is no digit, v1 is automatically bigger
        if(v1[i] > v2[i]) return true;
        if(v1[i] < v2[i]) return false;
      }
      return false; // Returns false if they are equal
    }

Based on Idan's awesome answer, the following function semverCompare passed most cases of semantic versioning 2.0.0. See this gist for more.

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

It returns:

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

this is my solution. it has accepted on leetcode. I met the problem in my interview today. But i did not solve it at that time. I thought about it again. Adding zeros to make the two arrays' length equal. Then comparison.

var compareVersion = function(version1, version2) {
    let arr1 = version1.split('.').map(Number);
    let arr2 = version2.split('.').map(Number);
    let diff = 0;
    if (arr1.length > arr2.length){
        diff = arr1.length - arr2.length;
        while (diff > 0){
            arr2.push(0);
            diff--;
        } 
    }
    else if (arr1.length < arr2.length){
        diff = arr2.length - arr1.length;
        while (diff > 0){
            arr1.push(0);
            diff--;
        }
    }
   
    let i = 0;
    while (i < arr1.length){
        if (arr1[i] > arr2[i]){
           return 1;
       } else if (arr1[i] < arr2[i]){
           return -1;
       }
        i++;
    }
    return 0;
    
};

The function will return -1 if the version are equal, 0 if the first version is the latest and 1 to indicate the second version is the latest.

let v1 = '12.0.1.0'
let v2 = '12.0.1'

let temp1 = v1.split('.');
let temp2 = v2.split('.');

console.log(compareVersion(temp1, temp2))


function compareVersion(version1, version2) {
    let flag = false;
    var compareResult;
    let maxLength = Math.max(version1.length, version2.length); 
    let minLength = Math.min(version1.length, version2.length);

    for (let i = 0; i < maxLength; ++i ) {
        let result = version1[i] - version2[i];
        if (result > 0) {
            flag = true;
            compareResult = 0;
            break;
        }
        else if (result < 0) {
            flag = true;
            compareResult = 1;
            break;
        }

        if (i === minLength) {
            if (version1.length > version1.length) {
                compareResult = version1[version1.length-1] > 0 ? '0' : '-1'
            }  else  {
                compareResult = version1[version2.length-1] > 0 ? '1' : '-1'
            }
            break;
        }
    }
    if (flag === false) {
        compareResult = -1;
    }
    return compareResult;
}

I didn't love any of the solutions so I rewrote it for my coding preferences. Notice the last four checks come out slightly different than the accepted answer. Works for me.

function v_check(version_a, version_b) {
    // compares version_a as it relates to version_b
    // a = b => "same"
    // a > b => "larger"
    // a < b => "smaller"
    // NaN   => "invalid"

    const arr_a = version_a.split('.');
    const arr_b = version_b.split('.');

    let result = "same"; // initialize to same // loop tries to disprove

    // loop through a and check each number against the same position in b
    for (let i = 0; i < arr_a.length; i++) {
        let a = arr_a[i];
        let b = arr_b[i];

        // same up to this point so if a is not there, a is smaller
        if (typeof a === 'undefined') {
            result = "smaller";
            break;

        // same up to this point so if b is not there, a is larger
        } else if (typeof b === 'undefined') {
            result = "larger";
            break;

        // otherwise, compare the two numbers
        } else {

            // non-positive numbers are invalid
            if (a >= 0 && b >= 0) {

                if (a < b) {
                    result = "smaller";
                    break;
                }
                else if (a > b) {
                    result = "larger";
                    break;
                }

            } else {
                result = "invalid";
                break;
            }
        }
    }

    // account for the case where the loop ended but there was still a position in b to evaluate
    if (result == "same" && arr_b.length > arr_a.length) result = "smaller";

    return result;
}


console.log(v_check("1.7.1", "1.7.10"));  // smaller
console.log(v_check("1.6.1", "1.7.10"));  // smaller
console.log(v_check("1.6.20", "1.7.10")); // smaller
console.log(v_check("1.7.1", "1.7.10"));  // smaller
console.log(v_check("1.7", "1.7.0"));     // smaller
console.log(v_check("1.7", "1.8.0"));     // smaller

console.log(v_check("1.7.10", "1.7.1"));  // larger
console.log(v_check("1.7.10", "1.6.1"));  // larger
console.log(v_check("1.7.10", "1.6.20")); // larger
console.log(v_check("1.7.0", "1.7"));     // larger
console.log(v_check("1.8.0", "1.7"));     // larger

console.log(v_check("1.7.10", "1.7.10")); // same
console.log(v_check("1.7", "1.7"));       // same

console.log(v_check("1.7", "1..7")); // larger
console.log(v_check("1.7", "Bad"));  // invalid
console.log(v_check("1..7", "1.7")); // smaller
console.log(v_check("Bad", "1.7"));  // invalid

I had to compare the version of my extension, but I did not find a working solution here. Almost all the proposed options break when comparing 1.89 > 1.9 or 1.24.1 == 1.240.1

Here I started from the fact that zeros go down only in the last record 1.1 == 1.10 and 1.10.1 > 1.1.1

compare_version = (new_version, old_version) => {
    new_version = new_version.split('.');
    old_version = old_version.split('.');
    for(let i = 0, m = Math.max(new_version.length, old_version.length); i<m; i++){
        //compare text
        let new_part = (i<m-1?'':'.') + (new_version[i] || 0)
        ,   old_part = (i<m-1?'':'.') + (old_version[i] || 0);
        //compare number (I don’t know what better)
      //let new_part = +((i<m-1?0:'.') + new_version[i]) || 0
      //,   old_part = +((i<m-1?0:'.') + old_version[i]) || 0;
        //console.log(new_part, old_part);
        if(old_part > new_part)return 0;    //change to -1 for sort the array
        if(new_part > old_part)return 1
    }
    return 0
};
compare_version('1.0.240.1','1.0.240.1');   //0
compare_version('1.0.24.1','1.0.240.1');    //0
compare_version('1.0.240.89','1.0.240.9');  //0
compare_version('1.0.24.1','1.0.24');       //1

I'm not a big specialist, but I built simple code to compare 2 versions, change the first return to -1 to sort the array of versions

['1.0.240', '1.0.24', '1.0.240.9', '1.0.240.89'].sort(compare_version)
//results ["1.0.24", "1.0.240", "1.0.240.89", "1.0.240.9"]

and short version for compare full string

c=e=>e.split('.').map((e,i,a)=>e[i<a.length-1?'padStart':'padEnd'](5)).join('');

//results "    1    0  2409    " > "    1    0  24089   "

c('1.0.240.9')>c('1.0.240.89')              //true

If you have comments or improvements, do not hesitate to suggest.

I have created this solution, and I hope you find it useful:

https://runkit.com/ecancino/5f3c6c59593d23001485992e


const quantify = max => (n, i) => n * (+max.slice(0, max.length - i))

const add = (a, b) => a + b

const calc = s => s.
    split('.').
    map(quantify('1000000')).
    reduce(add, 0)

const sortVersions = unsortedVersions => unsortedVersions
    .map(version => ({ version, order: calc(version) }))
    .sort((a, b) => a.order - b.order)
    .reverse()
    .map(o => o.version)

Here is my solution works for any level of depth for either version.

Auto deal with number+dot issue. If not so function exists and console log would give undefined instead of truthy false or true.

Auto deal with trailing zero issue.

Auto relay exists where ever possible.

Auto backward compatible on old browsers.

function checkVersion (vv,vvv){
if(!(/^[0-9.]*$/.test(vv) && /^[0-9.]*$/.test(vvv))) return;
va = vv.toString().split('.');
vb = vvv.toString().split('.');
length = Math.max(va.length, vb.length);
for (i = 0; i < length; i++) {

if ((va[i]|| 0) < (vb[i]|| 0)  ) {return false; } 
  }
  return true;}
  
  console.log(checkVersion('20.0.0.1' , '20.0.0.2'));
  console.log(checkVersion(20.0 , '20.0.0.2'));
  console.log(checkVersion('20.0.0.0.0' , 20));
  console.log(checkVersion('20.0.0.0.1' , 20));
  console.log(checkVersion('20.0.0-0.1' , 20));

I would like to advertise for the lightweight library I made to solve this problem: semantic-version

You can use it both object-oriented (OO) and function-oriented. It is available as npm-package and ready-to-use bundle files.

const compareAppVersions = (firstVersion, secondVersion) => {
  const firstVersionArray = firstVersion.split(".").map(Number);
  const secondVersionArray = secondVersion.split(".").map(Number);
  const loopLength = Math.max(
    firstVersionArray.length,
    secondVersionArray.length
  );
  for (let i = 0; i < loopLength; ++i) {
    const a = firstVersionArray[i] || 0;
    const b = secondVersionArray[i] || 0;
    if (a !== b) {
      return a > b ? 1 : -1;
    }
  }
  return 0;
};

function compare(versionA: string | undefined, versionB: string | undefined, operator: string = '>') {
    if (versionA === undefined || versionB === undefined) {
        return false
    }
    const listA = versionA.split('.')
    const listB = versionB.split('.')
    let a = []
    let b = []
    for (let i = 0; i < listA.length; i++) {
        a.push(parseInt(listA[i].replace(/\D/g, ''), 10))
        b.push(parseInt(listB[i].replace(/\D/g, ''), 10))
    }

    for (let i = 0; i < listA.length; i++) {
        switch (operator) {
            case '>':
            case '>=':
                if (a[i] === b[i]) {
                    continue
                }
                if (a[i] > b[i]) {
                    return true
                }
                if (a[i] < b[i]) {
                    return false
                }
                break
            case '<':
            case '<=':
                if (a[i] === b[i]) {
                    continue
                }
                if (a[i] > b[i]) {
                    return false
                }
                if (a[i] < b[i]) {
                    return true
                }
                break
            case '=':
               if (a[i] > b[i]) {
                   return false
               }
               if (a[i] < b[i]) {
                   return false
               }
               break
        }
    }
    switch (operator) {
        case '>':
            return false
        case '<':
            return false
        case '=':
        case '>=':
        case '<=':
            return true
    }
}

Convert it to a number, then compare. Let's say you use no more than 3 digits per major/minor/patch and no labels (like this 1.12.042)

const versionNumber = +versionString
  .split('.')
  .map(v => '000' + v)
  .map(v => v.slice(-3))
  .join('');

Two versions comparing

const val = '1.2.3 5.4.3';
const arr = val.split(' ');
let obj = {};
for(let i = 0; i<2; i++) {
    const splitArr = arr[i].split('.')
    const reduced = splitArr.reduce((pre, 
    curr)=>parseInt(pre)+parseInt(curr));
    obj[i] = reduced;
}
if(obj[0]>obj[1]) {
    console.log(arr[0]);
} else {
    console.log(arr[1]);
}
Related