Javascript function to compare two versions
Asked Answered
Y

7

5

Im writting a function to compare 2 versions, and return true if the second is bigger then first version.

but my algorithm have a "hole", and I cant figure out how fix.

function compareversion(version1,version2){

    var result=false;

    if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
    if(typeof version2!=='object'){ version2=version2.toString().split('.'); }

    for(var i=0;i<(Math.max(version1.length,version2.length));i++){

        if(version1[i]==undefined){ version1[i]=0; }
        if(version2[i]==undefined){ version2[i]=0; }

        if(version1[i]<version2[i]){
            result=true;
            break;
        }
    }
    return(result);
}

this exemples return as expected

compareversion('1','1') //false
compareversion('1','1.0.0') //false
compareversion('2.0','1.0.0') //false
compareversion('1.1','1.2') //true
compareversion('1','1.0.0.1') //true

but this

compareversion('1.1.0','1.0.1') //return true but should be false
Yenyenisei answered 28/10, 2011 at 16:4 Comment(1)
There is a same question here: #6833096 (link to my answer).Nainsook
S
7

This should work:

function compareversion(version1,version2){

    var result=false;

    if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
    if(typeof version2!=='object'){ version2=version2.toString().split('.'); }

    for(var i=0;i<(Math.max(version1.length,version2.length));i++){

        if(version1[i]==undefined){ version1[i]=0; }
        if(version2[i]==undefined){ version2[i]=0; }

        if(Number(version1[i])<Number(version2[i])){
            result=true;
            break;
        }
        if(version1[i]!=version2[i]){
            break;
        }
    }
    return(result);
}

The reason compareversion('1.1.0','1.0.1') fails is that your code first compares 1 to 1, then 1 to 0 (it does not break here since it only breaks if version1[i] < version2[i]) and then 0 to 1.

Since 0 < 1, it returns false.

Stapler answered 28/10, 2011 at 16:10 Comment(2)
Your algorithm isnt't working correctly if we compare '11.1.2' with '3.1.2' for example. You should convert the strings to integer before comparing. Please fix this! Nice algo by the way!Breastfeed
Here is Fiddle how it works (was testing if it would work for me) jsfiddle.net/fgprj51pThreesome
L
4

If version1 is at that index bigger, you know it should return false. You only need to continue if they are equal.

    if(version1[i]<version2[i]){
        result=true;
        break;
    }

    if(version1[i]>version2[i]){
        result=false;
        break;
    }

    // Will only get here if both are equal, in all other
    // cases you broke out of the loop. So only continue
    // checking the next index when this one was equal.
Lessen answered 28/10, 2011 at 16:10 Comment(0)
C
2

Your problem is that if you have 1.1.0 and 1.0.1, the function does not reach the break when you need it to

if(version1[i]<version2[i]){
   result=true;
   break;
}

it keeps comparing the numbers until the end.

you get 1<1 == false, the if does not run

then you get 1<0 == false, the if does not run

and then 0<1 == true, if makes result = true. you would need:

if(version1[i]<version2[i]){
   return true;
}else 
  if(version1[i]>version2[i]){
        return false;
  }
Chrissa answered 28/10, 2011 at 16:20 Comment(0)
K
1

None of these answers is optimal for the following reasons:

  1. your parameters being passed in can be strings. later on you convert them to an array. this is expensive and goes against good coding practice. NEVER change the type of a variable after it has been initialised! Create a new variable to hold the array.
  2. The function continues through the loop even after it has enough info to return with a result.

You basically want to start at the major version and work down to the minor version. As soon as you find one that is not equal, you want to return. It is standard when doing a greater than, less than operation in function(a,b) that the return value of the function should be :

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

Otherwise, anyone calling this function would not know what it returns true for unless they look at the internals of it. If minified and obfuscated, this could be a waste of time.

I have rewritten and improved the function with this in mind.

function (versionA, versionB) {
  var arrA,
      arrB;

  arrA = typeof versionA !== 'object' ? versionA.toString().split('.') : versionA;
  arrB = typeof versionB !== 'object' ? versionB.toString().split('.') : versionB;

  for (var i = 0; i < (Math.max(arrA.length, arrB.length)); i++) {
    arrA[i] = typeof arrA[i] === 'undefined' ? 0 : Number(arrA[i]);
    arrB[i] = typeof arrB[i] === 'undefined' ? 0 : Number(arrB[i]);

    if (arrA[i] > arrB[i]) {
      return 1;
    }
    if (arrA[i] < arrB[i]) {
      return -1;
    }
  }
  return 0;
};
Kelleekelleher answered 12/10, 2012 at 12:20 Comment(0)
W
0
version1 = version1.toString();
version2 = version2.toString();
var matchFound = false;

if(version1.length != version2.length){
//Different Versions
}else{
//They are the same length so compare each element
FIND:  
for(var i = 0; i < version1.length; i++){
   var match = version[i].match(version2[i]){     
   if(match == ""){
     //Match found 
     matchFound = true;
     break FIND;
   }
}
return matchFound;
Wendelin answered 28/10, 2011 at 16:16 Comment(2)
this function have a problem, comparing 1.0 to 1.0.0 should be the same version.Yenyenisei
I was assuming that the version numbers would follow a format. Sorry about that.Wendelin
B
0

Using localeCompare works pretty well.
The below link have my solution used in comparing version number

https://mcmap.net/q/1922936/-how-is-version-number-comparison-working-correctly-in-javascript

Bevan answered 16/9, 2022 at 20:11 Comment(0)
P
0

For my use case neither of the solution above didn't worked properly, so I've started from the accepted answer and improve it in order to compare the following version formats:

  • "1.01.5" with "2"
  • "1.01.5" with "1.9"
  • "1.01.5" with "1.09"
  • "1.04.10" with "1.05.02"
  • "1.01.5" with "1.01.6"
  • "1.5.5" with "1.5.6"
  • "1" with "2"
  • "1.1" with "1.2"
  • "1.1" with "1.05"
  • "1" with "1.0.0.1"
  • etc

In my case I return true if the first version is bigger or equal with the second one. If you want that the logic to be the other way around (as described in the initial post), swap the return values inside the for loop (or the comparison signs) and if you don't want to be true for equal values, last return make it false.

const compareVersions = (version1, version2) => {

    if(typeof version1 !== 'object'){ version1 = version1.toString().split('.') }
    if(typeof version2 !== 'object'){ version2 = version2.toString().split('.') }

    for( let i=0; i<(Math.max(version1.length,version2.length)); i++ ) {
        if(version1[i] == undefined) { version1[i] = 0 }
        if(version2[i] == undefined) { version2[i] = 0 }

        if(version1[i]) { 
            if(version1[i].length > 1 && version1[i][0] === "0") {
                version1[i] = version1[i].replace("0", "0.")
            }
        }

        if(version2[i]) {
            if(version2[i].length > 1 && version2[i][0] === "0") {
                version2[i] = version2[i].replace("0", "0.")
            }
        }

        const v1 = Number(version1[i])
        const v2 = Number(version2[i])

        if(v1 > v2) {
            return true
        }

        if(v1 < v2) {
            return false
        }
    }

    return true
}
Prussiate answered 16/7 at 19:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.