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
Vitim.us
  • 20,746
  • 15
  • 92
  • 109
  • There is a same question here: https://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number#answer-52059759 (link to my answer). – Arthur Ronconi Aug 28 '18 at 14:07

6 Answers6

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.

Dennis
  • 14,264
  • 2
  • 48
  • 57
  • 1
    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! – Tamás Pap Sep 08 '12 at 07:59
  • Here is Fiddle how it works (was testing if it would work for me) http://jsfiddle.net/fgprj51p/ – Grzegorz Sep 19 '15 at 17:05
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.
pimvdb
  • 151,816
  • 78
  • 307
  • 352
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;
  }
alinn
  • 311
  • 2
  • 7
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;
};
Stumpy7
  • 252
  • 3
  • 14
0

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

https://stackoverflow.com/a/73749865/13970597

Cito
  • 26
  • 6
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;
Reid Mac
  • 2,411
  • 6
  • 37
  • 64