以下是软件版本号:
"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指定
这适用于由句点分隔的任何长度的数字版本。只有当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);
}
虽然这个问题已经有很多答案,但每个人都在推广自己的解决方案,而我们有一个完整的生态系统(战斗)测试库。
在NPM, GitHub, X上快速搜索会给我们一些可爱的lib,我想要运行一些:
Semver-compare是一个很棒的轻量级库(约230字节),如果您想按版本号排序,它尤其有用,因为库的公开方法会适当地返回-1、0或1。
库的核心:
module.exports = function cmp (a, b) {
var pa = a.split('.');
var pb = b.split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
if (na > nb) return 1;
if (nb > na) return -1;
if (!isNaN(na) && isNaN(nb)) return 1;
if (isNaN(na) && !isNaN(nb)) return -1;
}
return 0;
};
compare-semver的大小相当大(大约4.4 kB gzip),但是允许进行一些很好的惟一比较,比如查找一堆版本的最小/最大值,或者查找所提供的版本是惟一的还是比版本集合中的其他任何版本都小。
compare-versions是另一个小库(大约630字节gzip),它很好地遵循规范,这意味着你可以比较带有alpha/beta标志甚至通配符的版本(比如minor/patch版本:1.0)。X或1.0)
重点是:如果你能通过你选择的包管理器找到合适的(单元)测试版本,那么并不总是需要从Stack Overflow复制粘贴代码。
比较不同条件下的功能:
const compareVer = (ver1, middle, ver2) => {
const res = new Intl.Collator("en").compare(ver1, ver2)
let comp
switch (middle) {
case "=":
comp = 0 === res
break
case ">":
comp = 1 === res
break
case ">=":
comp = 1 === res || 0 === res
break
case "<":
comp = -1 === res
break
case "<=":
comp = -1 === res || 0 === res
break
}
return comp
}
console.log(compareVer("1.0.2", "=", "1.0.2")) // true
console.log(compareVer("1.0.3", ">", "1.0.2")) // true
console.log(compareVer("1.0.1", ">=", "1.0.2")) // false
console.log(compareVer("1.0.3", ">=", "1.0.2")) // true
console.log(compareVer("1.0.1", "<", "1.0.2")) // true
console.log(compareVer("1.0.1", "<=", "1.0.2")) // true
我已经创建了这个解决方案,我希望你觉得它有用:
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)