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
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
Share
Improve this question
asked Oct 28, 2011 at 16:04
Vitim.usVitim.us
22.1k15 gold badges99 silver badges114 bronze badges
1
- There is a same question here: stackoverflow.com/questions/6832596/… (link to my answer). – Arthur Ronconi Commented Aug 28, 2018 at 14:07
7 Answers
Reset to default 7This 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
.
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.
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;
}
None of these answers is optimal for the following reasons:
- 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.
- 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;
};
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;
Using localeCompare
works pretty well.
The below link have my solution used in comparing version number
https://stackoverflow.com/a/73749865/13970597
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
}