以下是软件版本号:
"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"
这样可以更清楚地看到背后的想法。
但是,我怎样才能把它转换成计算机程序呢?
这不是一个很好的解决问题的方法,但它非常相似。
这个排序函数是针对语义版本的,它处理的是解析版本,所以它不能处理像x或*这样的通配符。
它适用于正则表达式匹配的版本:/\d+\.\d+\.\d+.*$/。它与这个答案非常相似,除了它也适用于像1.2.3-dev这样的版本。
与另一个答案的比较:我删除了一些我不需要的检查,但我的解决方案可以与另一个相结合。
semVerSort = function(v1, v2) {
var v1Array = v1.split('.');
var v2Array = v2.split('.');
for (var i=0; i<v1Array.length; ++i) {
var a = v1Array[i];
var b = v2Array[i];
var aInt = parseInt(a, 10);
var bInt = parseInt(b, 10);
if (aInt === bInt) {
var aLex = a.substr((""+aInt).length);
var bLex = b.substr((""+bInt).length);
if (aLex === '' && bLex !== '') return 1;
if (aLex !== '' && bLex === '') return -1;
if (aLex !== '' && bLex !== '') return aLex > bLex ? 1 : -1;
continue;
} else if (aInt > bInt) {
return 1;
} else {
return -1;
}
}
return 0;
}
合并后的解为:
function versionCompare(v1, v2, options) {
var zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
var v1Int = parseInt(v1parts[i], 10);
var v2Int = parseInt(v2parts[i], 10);
if (v1Int == v2Int) {
var v1Lex = v1parts[i].substr((""+v1Int).length);
var v2Lex = v2parts[i].substr((""+v2Int).length);
if (v1Lex === '' && v2Lex !== '') return 1;
if (v1Lex !== '' && v2Lex === '') return -1;
if (v1Lex !== '' && v2Lex !== '') return v1Lex > v2Lex ? 1 : -1;
continue;
}
else if (v1Int > v2Int) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
看看这篇博客文章。此函数适用于数字版本号。
function compVersions(strV1, strV2) {
var nRes = 0
, parts1 = strV1.split('.')
, parts2 = strV2.split('.')
, nLen = Math.max(parts1.length, parts2.length);
for (var i = 0; i < nLen; i++) {
var nP1 = (i < parts1.length) ? parseInt(parts1[i], 10) : 0
, nP2 = (i < parts2.length) ? parseInt(parts2[i], 10) : 0;
if (isNaN(nP1)) { nP1 = 0; }
if (isNaN(nP2)) { nP2 = 0; }
if (nP1 != nP2) {
nRes = (nP1 > nP2) ? 1 : -1;
break;
}
}
return nRes;
};
compVersions('10', '10.0'); // 0
compVersions('10.1', '10.01.0'); // 0
compVersions('10.0.1', '10.0'); // 1
compVersions('10.0.1', '10.1'); // -1
我找到了最简单的方法来比较它们,但我不确定这是否是你想要的。
当我在控制台中运行下面的代码时,它是有意义的,并且使用sort()方法,我可以获得版本字符串的排序数组。它是根据字母顺序排列的。
"1.0" < "1.0.1" //true
var arr = ["1.0.1", "1.0", "3.2.0", "1.3"]
arr.sort(); //["1.0", "1.0.1", "1.3", "3.2.0"]
这不是一个很好的解决问题的方法,但它非常相似。
这个排序函数是针对语义版本的,它处理的是解析版本,所以它不能处理像x或*这样的通配符。
它适用于正则表达式匹配的版本:/\d+\.\d+\.\d+.*$/。它与这个答案非常相似,除了它也适用于像1.2.3-dev这样的版本。
与另一个答案的比较:我删除了一些我不需要的检查,但我的解决方案可以与另一个相结合。
semVerSort = function(v1, v2) {
var v1Array = v1.split('.');
var v2Array = v2.split('.');
for (var i=0; i<v1Array.length; ++i) {
var a = v1Array[i];
var b = v2Array[i];
var aInt = parseInt(a, 10);
var bInt = parseInt(b, 10);
if (aInt === bInt) {
var aLex = a.substr((""+aInt).length);
var bLex = b.substr((""+bInt).length);
if (aLex === '' && bLex !== '') return 1;
if (aLex !== '' && bLex === '') return -1;
if (aLex !== '' && bLex !== '') return aLex > bLex ? 1 : -1;
continue;
} else if (aInt > bInt) {
return 1;
} else {
return -1;
}
}
return 0;
}
合并后的解为:
function versionCompare(v1, v2, options) {
var zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
var v1Int = parseInt(v1parts[i], 10);
var v2Int = parseInt(v2parts[i], 10);
if (v1Int == v2Int) {
var v1Lex = v1parts[i].substr((""+v1Int).length);
var v2Lex = v2parts[i].substr((""+v2Int).length);
if (v1Lex === '' && v2Lex !== '') return 1;
if (v1Lex !== '' && v2Lex === '') return -1;
if (v1Lex !== '' && v2Lex !== '') return v1Lex > v2Lex ? 1 : -1;
continue;
}
else if (v1Int > v2Int) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
这里有一个面向对象的有趣方法:
function versionString(str) {
var parts = str.split('.');
this.product = parts.length > 0 ? parts[0] * 1 : 0;
this.major = parts.length > 1 ? parts[1] * 1 : 0;
this.minor = parts.length > 2 ? parts[2] * 1 : 0;
this.build = parts.length > 3 ? parts[3] * 1 : 0;
this.compareTo = function(vStr){
vStr = this._isVersionString(vStr) ? vStr : new versionString(vStr);
return this.compare(this, vStr);
};
this.toString = function(){
return this.product + "." + this.major + "." + this.minor + "." + this.build;
}
this.compare = function (str1, str2) {
var vs1 = this._isVersionString(str1) ? str1 : new versionString(str1);
var vs2 = this._isVersionString(str2) ? str2 : new versionString(str2);
if (this._compareNumbers(vs1.product, vs2.product) == 0) {
if (this._compareNumbers(vs1.major, vs2.major) == 0) {
if (this._compareNumbers(vs1.minor, vs2.minor) == 0) {
return this._compareNumbers(vs1.build, vs2.build);
} else {
return this._compareNumbers(vs1.minor, vs2.minor);
}
} else {
return this._compareNumbers(vs1.major, vs2.major);
}
} else {
return this._compareNumbers(vs1.product, vs2.product);
}
};
this._isVersionString = function (str) {
return str !== undefined && str.build !== undefined;
};
this._compareNumbers = function (n1, n2) {
if (n1 > n2) {
return 1;
} else if (n1 < n2) {
return -1;
} else {
return 0;
}
};
}
还有一些测试:
var v1 = new versionString("1.0");
var v2 = new versionString("1.0.1");
var v3 = new versionString("2.0");
var v4 = new versionString("2.0.0.1");
var v5 = new versionString("2.0.1");
alert(v1.compareTo("1.4.2"));
alert(v3.compareTo(v1));
alert(v5.compareTo(v4));
alert(v4.compareTo(v5));
alert(v5.compareTo(v5));
如果不允许使用字母或符号,那么代码行数就很少。如果您控制了版本控制方案,并且不是第三方提供的,那么这种方法是有效的。
// we presume all versions are of this format "1.4" or "1.10.2.3", without letters
// returns: 1 (bigger), 0 (same), -1 (smaller)
function versionCompare (v1, v2) {
const v1Parts = v1.split('.')
const v2Parts = v2.split('.')
const length = Math.max(v1Parts.length, v2Parts.length)
for (let i = 0; i < length; i++) {
const value = (parseInt(v1Parts[i]) || 0) - (parseInt(v2Parts[i]) || 0)
if (value < 0) return -1
if (value > 0) return 1
}
return 0
}
console.log(versionCompare('1.2.0', '1.2.4') === -1)
console.log(versionCompare('1.2', '1.2.0') === 0)
console.log(versionCompare('1.2', '1') === 1)
console.log(versionCompare('1.2.10', '1.2.1') === 1)
console.log(versionCompare('1.2.134230', '1.2.2') === 1)
console.log(versionCompare('1.2.134230', '1.3.0.1.2.3.1') === -1)