以下是软件版本号:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
我怎么比较呢?
假设正确的顺序是:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
想法很简单…
读第一个数字,然后,第二个,第三个…
但是我不能将版本号转换为浮点数…
你也可以像这样看到版本号:
"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"
这样可以更清楚地看到背后的想法。
但是,我怎样才能把它转换成计算机程序呢?
我也遇到了版本比较的问题,但是版本可能包含任何内容(例如:不是点的分隔符,像rc1, rc2…)
我使用了这个方法,它基本上将版本字符串分为数字和非数字,并尝试根据类型进行比较。
function versionCompare(a,b) {
av = a.match(/([0-9]+|[^0-9]+)/g)
bv = b.match(/([0-9]+|[^0-9]+)/g)
for (;;) {
ia = av.shift();
ib = bv.shift();
if ( (typeof ia === 'undefined') && (typeof ib === 'undefined') ) { return 0; }
if (typeof ia === 'undefined') { ia = '' }
if (typeof ib === 'undefined') { ib = '' }
ian = parseInt(ia);
ibn = parseInt(ib);
if ( isNaN(ian) || isNaN(ibn) ) {
// non-numeric comparison
if (ia < ib) { return -1;}
if (ia > ib) { return 1;}
} else {
if (ian < ibn) { return -1;}
if (ian > ibn) { return 1;}
}
}
}
对于某些情况,这里有一些假设,例如:"1.01" === "1.1",或"1.8" < "1.71"。它无法管理“1.0.0-rc”。1" < "1.0.0",由语义版本2.0.0指定
2017答:
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;
}
最简单的现代浏览器代码:
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;
}
这里的想法是比较数字,但以字符串的形式。为了使比较工作,两个字符串必须在相同的长度。所以:
"123" > "99"变成"123" > "099"
填充短数字“修复”比较
这里我用0填充每个部分,长度为10。然后使用简单的字符串比较来得到答案
例子:
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
一个非常简单的方法:
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';
}
}
输出:
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
例如,如果我们想检查当前jQuery版本是否小于1.8,如果version是"1.10.1",parseFloat($.ui.version) < 1.8)将会给出错误的结果,因为parseFloat("1.10.1")返回1.1。
字符串比较也会出错,因为"1.8" < "1.10"的结果为false。
所以我们需要一个这样的测试
if(versionCompare($.ui.version, "1.8") < 0){
alert("please update jQuery");
}
下面的函数可以正确地处理这个问题:
/** Compare two dotted version strings (like '10.2.3').
* @returns {Integer} 0: v1 == v2, -1: v1 < v2, 1: v1 > v2
*/
function versionCompare(v1, v2) {
var v1parts = ("" + v1).split("."),
v2parts = ("" + v2).split("."),
minLength = Math.min(v1parts.length, v2parts.length),
p1, p2, i;
// Compare tuple pair-by-pair.
for(i = 0; i < minLength; i++) {
// Convert to integer if possible, because "8" > "10".
p1 = parseInt(v1parts[i], 10);
p2 = parseInt(v2parts[i], 10);
if (isNaN(p1)){ p1 = v1parts[i]; }
if (isNaN(p2)){ p2 = v2parts[i]; }
if (p1 == p2) {
continue;
}else if (p1 > p2) {
return 1;
}else if (p1 < p2) {
return -1;
}
// one operand is NaN
return NaN;
}
// The longer tuple is always considered 'greater'
if (v1parts.length === v2parts.length) {
return 0;
}
return (v1parts.length < v2parts.length) ? -1 : 1;
}
下面是一些例子:
// compare dotted version strings
console.assert(versionCompare("1.8", "1.8.1") < 0);
console.assert(versionCompare("1.8.3", "1.8.1") > 0);
console.assert(versionCompare("1.8", "1.10") < 0);
console.assert(versionCompare("1.10.1", "1.10.1") === 0);
// Longer is considered 'greater'
console.assert(versionCompare("1.10.1.0", "1.10.1") > 0);
console.assert(versionCompare("1.10.1", "1.10.1.0") < 0);
// Strings pairs are accepted
console.assert(versionCompare("1.x", "1.x") === 0);
// Mixed int/string pairs return NaN
console.assert(isNaN(versionCompare("1.8", "1.x")));
//works with plain numbers
console.assert(versionCompare("4", 3) > 0);
看到这里的现场示例和测试套件:
http://jsfiddle.net/mar10/8KjvP/