以下是软件版本号:
"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 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));
这里找不到我想要的函数。所以我自己写了。这就是我的贡献。我希望有人觉得它有用。
优点:
处理任意长度的版本字符串。'1'或'1.1.1.1.1'。
如果没有指定,则默认为0。仅仅因为字符串更长并不意味着它是一个更大的版本。(“1”应与“1.0”和“1.0.0.0”相同。)
比较数字而不是字符串。('3'<'21'应为真。不是假的。)
不要把时间浪费在无用的比较上。(比较for ==)
你可以选择你自己的比较器。
缺点:
它不处理版本字符串中的字母。(我不知道这是怎么回事?)
我的代码,类似于Jon接受的答案:
function compareVersions(v1, comparator, v2) {
"use strict";
var comparator = comparator == '=' ? '==' : comparator;
if(['==','===','<','<=','>','>=','!=','!=='].indexOf(comparator) == -1) {
throw new Error('Invalid comparator. ' + comparator);
}
var v1parts = v1.split('.'), v2parts = v2.split('.');
var maxLen = Math.max(v1parts.length, v2parts.length);
var part1, part2;
var cmp = 0;
for(var i = 0; i < maxLen && !cmp; i++) {
part1 = parseInt(v1parts[i], 10) || 0;
part2 = parseInt(v2parts[i], 10) || 0;
if(part1 < part2)
cmp = 1;
if(part1 > part2)
cmp = -1;
}
return eval('0' + comparator + cmp);
}
例子:
compareVersions('1.2.0', '==', '1.2'); // true
compareVersions('00001', '==', '1.0.0'); // true
compareVersions('1.2.0', '<=', '1.2'); // true
compareVersions('2.2.0', '<=', '1.2'); // false
这适用于由句点分隔的任何长度的数字版本。只有当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);
}
我必须比较我的扩展版本,但我没有
在这里找到一个可行的解决方案。在比较1.89 > 1.9或1.24.1 == 1.240.1时,几乎所有提议的期权都被打破了
这里,我从仅在最后的记录1.1 == 1.10和1.10.1 > 1.1.1中0下降的事实开始
compare_version = (new_version, old_version) => {
new_version = new_version.split('.');
old_version = old_version.split('.');
for(let i = 0, m = Math.max(new_version.length, old_version.length); i<m; i++){
//compare text
let new_part = (i<m-1?'':'.') + (new_version[i] || 0)
, old_part = (i<m-1?'':'.') + (old_version[i] || 0);
//compare number (I don’t know what better)
//let new_part = +((i<m-1?0:'.') + new_version[i]) || 0
//, old_part = +((i<m-1?0:'.') + old_version[i]) || 0;
//console.log(new_part, old_part);
if(old_part > new_part)return 0; //change to -1 for sort the array
if(new_part > old_part)return 1
}
return 0
};
compare_version('1.0.240.1','1.0.240.1'); //0
compare_version('1.0.24.1','1.0.240.1'); //0
compare_version('1.0.240.89','1.0.240.9'); //0
compare_version('1.0.24.1','1.0.24'); //1
我不是一个大专家,但我构建了简单的代码来比较两个版本,将第一个返回值更改为-1以对版本数组进行排序
['1.0.240', '1.0.24', '1.0.240.9', '1.0.240.89'].sort(compare_version)
//results ["1.0.24", "1.0.240", "1.0.240.89", "1.0.240.9"]
和短版本的比较全字符串
c=e=>e.split('.').map((e,i,a)=>e[i<a.length-1?'padStart':'padEnd'](5)).join('');
//results " 1 0 2409 " > " 1 0 24089 "
c('1.0.240.9')>c('1.0.240.89') //true
如果您有意见或改进,请不要犹豫提出建议。