以下是软件版本号:
"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"
这样可以更清楚地看到背后的想法。
但是,我怎样才能把它转换成计算机程序呢?
看看这篇博客文章。此函数适用于数字版本号。
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
以下是我的解决方案,适用于任何深度的任何版本。
自动处理数字+点问题。如果不是这样,函数存在,控制台日志将给出undefined而不是true, false或true。
自动处理尾随零问题。
任何可能的地方都存在自动继电器。
自动向后兼容旧浏览器。
function checkVersion (vv,vvv){
if(!(/^[0-9.]*$/.test(vv) && /^[0-9.]*$/.test(vvv))) return;
va = vv.toString().split('.');
vb = vvv.toString().split('.');
length = Math.max(va.length, vb.length);
for (i = 0; i < length; i++) {
if ((va[i]|| 0) < (vb[i]|| 0) ) {return false; }
}
return true;}
console.log(checkVersion('20.0.0.1' , '20.0.0.2'));
console.log(checkVersion(20.0 , '20.0.0.2'));
console.log(checkVersion('20.0.0.0.0' , 20));
console.log(checkVersion('20.0.0.0.1' , 20));
console.log(checkVersion('20.0.0-0.1' , 20));
我已经创建了这个解决方案,我希望你觉得它有用:
https://runkit.com/ecancino/5f3c6c59593d23001485992e
const quantify = max => (n, i) => n * (+max.slice(0, max.length - i))
const add = (a, b) => a + b
const calc = s => s.
split('.').
map(quantify('1000000')).
reduce(add, 0)
const sortVersions = unsortedVersions => unsortedVersions
.map(version => ({ version, order: calc(version) }))
.sort((a, b) => a.order - b.order)
.reverse()
.map(o => o.version)
这适用于由句点分隔的任何长度的数字版本。只有当myVersion为>= minimumVersion时,它才返回true,假设版本1小于1.0,版本1.1小于1.1.0,以此类推。添加额外的条件应该相当简单,比如接受数字(只需转换为字符串)和十六进制,或者使分隔符动态(只需添加一个分隔符参数,然后将“。”替换为参数)
function versionCompare(myVersion, minimumVersion) {
var v1 = myVersion.split("."), v2 = minimumVersion.split("."), minLength;
minLength= Math.min(v1.length, v2.length);
for(i=0; i<minLength; i++) {
if(Number(v1[i]) > Number(v2[i])) {
return true;
}
if(Number(v1[i]) < Number(v2[i])) {
return false;
}
}
return (v1.length >= v2.length);
}
下面是一些测试:
console.log(versionCompare("4.4.0","4.4.1"));
console.log(versionCompare("5.24","5.2"));
console.log(versionCompare("4.1","4.1.2"));
console.log(versionCompare("4.1.2","4.1"));
console.log(versionCompare("4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("4.4.4.4.4.4","4.4.4.4.4"));
console.log(versionCompare("0","1"));
console.log(versionCompare("1","1"));
console.log(versionCompare("","1"));
console.log(versionCompare("10.0.1","10.1"));
这里有一个递归版本
function versionCompare(myVersion, minimumVersion) {
return recursiveCompare(myVersion.split("."),minimumVersion.split("."),Math.min(myVersion.length, minimumVersion.length),0);
}
function recursiveCompare(v1, v2,minLength, index) {
if(Number(v1[index]) < Number(v2[index])) {
return false;
}
if(Number(v1[i]) < Number(v2[i])) {
return true;
}
if(index === minLength) {
return (v1.length >= v2.length);
}
return recursiveCompare(v1,v2,minLength,index+1);
}
你不能把它们转换成数字,然后按大小排序吗?在长度< 4的数的1后面加上0
在主机上玩:
$(["1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1", "3.0"]).each(function(i,e) {
var n = e.replace(/\./g,"");
while(n.length < 4) n+="0" ;
num.push( +n )
});
版本越大,数字越大。
编辑:可能需要调整,以考虑更大的版本系列
这不是一个很好的解决问题的方法,但它非常相似。
这个排序函数是针对语义版本的,它处理的是解析版本,所以它不能处理像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;
}