I have a version number with 3 digits as a String,
var version = "1.2.3";
and would like to compare it to another version. To see if version is newer than otherversion,
var otherVersion = "1.2.4";
How would you do it?
I have a version number with 3 digits as a String,
var version = "1.2.3";
and would like to compare it to another version. To see if version is newer than otherversion,
var otherVersion = "1.2.4";
How would you do it?
Pseudo:
.(See @arhorns answer for a elegant implementation)
The problem with most of the submitted versions is they can't handle any number of version parts (eg. 1.4.2 .. 1.2 etc) and/or they have the requirement of the version part being a single digit, which is not that common actually.
Improved compareVersions() function
This function will return 1 if v1 is greater than v2, -1 if v2 is greater and 0 if the versions are equal (handy for custom sorting as well)
I'm not doing any error checking on the inputs.
function compareVersions (v1, v2)
{
v1 = v1.split('.');
v2 = v2.split('.');
var longestLength = (v1.length > v2.length) ? v1.length : v2.length;
for (var i = 0; i < longestLength; i++) {
if (v1[i] != v2[i]) {
return (v1 > v2) ? 1 : -1
}
}
return 0;
}
var longestLength = Math.max(v1.length, v2.length);compareVersions('1.2.3', '1.2.3.0') will return -1, but I guess it should return 0. You may want to use the || operator to default an undefined to 0 in (v1[i] != v2[i]). In addition, you have a typo in i < longestLenght.compareVersions('1.2.3', '1.2.10') will also return 1 when it should return -1. You need parseInt() to fix this.You may want to use the following implementation (based on jensgram's solution):
function isNewer(a, b) {
var partsA = a.split('.');
var partsB = b.split('.');
var numParts = partsA.length > partsB.length ? partsA.length : partsB.length;
var i;
for (i = 0; i < numParts; i++) {
if ((parseInt(partsB[i], 10) || 0) !== (parseInt(partsA[i], 10) || 0)) {
return ((parseInt(partsB[i], 10) || 0) > (parseInt(partsA[i], 10) || 0));
}
}
return false;
}
console.log(isNewer('1.2.3', '1.2.4')); // true
console.log(isNewer('1.2.3', '1.2.0')); // false
console.log(isNewer('1.2.3', '1.2.3.1')); // true
console.log(isNewer('1.2.3', '1.2.2.9')); // false
console.log(isNewer('1.2.3', '1.2.10')); // true
Note that the use of parseInt() is necessary, because otherwise the last test would return false: "10" > "3" returns false.
for each (i in aVersion) ? For an array? Why?If indeed you only have a single digit in each part why not just use straight comparison?
>>> var version = "1.2.3"; var otherVersion = "1.2.4"; version < otherVersion
true
It seems also to work with abbreviated versions:
>>> '1.2' > '1.2.4'
false
>>> '1.3' > '1.2.4'
true
'1.2' > '1.2.3' comparison works perfectly fine.With one of the comparison operators.
"1.2.3" > "1.2.4" //false
"1.2.3" < "1.2.4" //true
"1.2.3" < "1.2.10" // false but should be true"foo.bar.wibble.wobble", "044.0x99.6" or null. Most of the more complicated solutions here are equally as unstable.function VersionValue(var str)
{
var tmp = str.split('.');
return (tmp[0] * 100) + (tmp[1] * 10) + tmp[2];
}
if (VersionValue(version) > VersionValue(otherVersion))...
for example
Since I'm bored, here's an approach similar to our decimal system (tens, hundreds, thousands, etc) which uses a regex callback instead of a loop:
function compareVersion(a, b) {
var expr = /\d+/g, places = Math.max(a.split(expr).length, b.split(expr).length);
function convert(s) {
var place = Math.pow(100, places), total = 0;
s.replace(expr,
function (n) {
total += n * place;
place /= 100;
}
);
return total;
};
if (convert(a) > convert(b)) {
return a;
}
return b;
}
It returns the greater version, e.g.:
compareVersion('1.4', '1.3.99.32.60.4'); // => 1.4
function isCorrectVersion(used,required){
var used = parseFloat("0."+used.replace(/\./gi,""));
var required = parseFloat("0."+required.replace(/\./gi,""));
return (used < required) ? false : true;
}
I use this to compare jQuery functions and it seems to work fine, also comparing for example 1.4 with 1.4.1 or 1.4.1 with 1.4.11.
I couldnt find an answer that returns 1, 0 or -1 and takes care of both trailing .0 and two digit partials, so here goes. This should support all cases where all the partials are numbers (see the tests at the bottom).
/*
* Returns 1 if v1 is newer, -1 if v2 is newer and 0 if they are equal.
* .0s at the end of the version will be ignored.
*
* If a version evaluates to false it will be treated as 0.
*
* Examples:
* compareVersions ("2.0", "2") outputs 0,
* compareVersions ("2.0.1", "2") outputs 1,
* compareVersions ("0.2", "0.12.1") outputs -1,
*
*/
function compareVersions (version1, version2) {
var version1 = version1 ? version1.split('.') : ['0'],
version2 = version2 ? version2.split('.') : ['0'],
longest = Math.max(version1.length, version2.length);
for (var i = 0; i < longest; i++) {
/*
* Convert to ints so that we can compare two digit parts
* properly. (Otherwise would "2" be greater than "12").
*
* This returns NaN if the value is undefined, so we check for
* NaN later.
*/
var v1Part = parseInt(version1[i]),
v2Part = parseInt(version2[i]);
if (v1Part != v2Part) {
// version2 is longer
if (isNaN(v1Part)) {
/*
* Go through the rest of the parts of version 2. If it is only zeros,
* consider the versions equal, otherwise consider version 2 as newer.
*/
for (var j = i; j < longest; j++) {
if (parseInt(version2[j]) != 0) return -1;
}
// version1 is longer
} else if (isNaN(v2Part)) {
for (var j = i; j < longest; j++) {
if (parseInt(version1[j]) != 0) return 1;
}
// versions are equally long
} else {
return (v1Part > v2Part) ? 1 : -1;
}
return 0;
}
}
return 0;
}
console.log(compareVersions("1", "1") === 0);
console.log(compareVersions("1.1", "1") === 1);
console.log(compareVersions("1.1.1", "1") === 1);
console.log(compareVersions("1", "1.1.1") === -1);
console.log(compareVersions("0.3", "0.3.0.0.1") === -1);
console.log(compareVersions("0.3", "0.3.0") === 0);
console.log(compareVersions("0.3.0.0.1", "0.3") === 1);
console.log(compareVersions("0.3.0", "0.3") === 0);
console.log(compareVersions("0.12", "0.2") === 1);
console.log(compareVersions("0.2", "0.12") === -1);
console.log(compareVersions("0.12.0", "0.2") === 1);
console.log(compareVersions("0.02.0", "0.2") === 0);
console.log(compareVersions("0.01.0", "0.2") === -1);
Note, that none of these solutions will knowingly return the right result for things like 0.9beta or 1.0 RC 1. It is, however, handled quite intuitively in PHP: http://de3.php.net/manual/en/function.version-compare.php and there is a JS port of this: http://phpjs.org/functions/version_compare (I don't claim this to be very nice or efficient, just kind of 'complete').
Maybe like this (quickie)?
function isNewer(s0, s1) {
var v0 = s0.split('.'), v1 = s1.split('.');
var len0 = v0.length, len1=v1.length;
var temp0, temp1, idx = 0;
while (idx<len0) {
temp0 = parseInt(v0[idx], 10);
if (len1>idx) {
temp1 = parseInt(v1[idx], 10);
if (temp1>temp0) {return true;}
}
idx += 1;
}
if (parseInt(v0[idx-1], 10)>parseInt(v1[idx-1], 10)) {return false;}
return len1 > len0;
}
var version = "1.2.3";
var otherVersion = "1.2.4";
console.log('newer:'+(isNewer(version, otherVersion)));
It takes care of different number of parts, but it works only with numbers between the dots though.
parseInt(x, 10) because without specifying the base, isNewer("1.2.03", "1.2.08") returns false, while isNewer("1.2.03", "1.2.07") returns true.