Javascript 如何使用js比较软件版本号?(只有数字)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6832596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to compare software version number using js? (only number)
提问by Tattat
Here is the software version number:
这是软件版本号:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
How can I compare this?? Assume the correct order is:
我怎么能比较这个??假设正确的顺序是:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
The idea is simple...: Read the first digit, than, the second, after that the third.... But I can't convert the version number to float number.... You also can see the version number like this:
这个想法很简单......:读取第一个数字,然后,第二个,然后是第三个......但我无法将版本号转换为浮点数......你也可以看到版本号这个:
"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"
and this is more clear to see what is the idea behind... But, how to convert it into a computer program?? Do any one have any idea on how to sorting this? Thank you.
这更清楚地看到背后的想法......但是,如何将其转换为计算机程序??有没有人知道如何对此进行排序?谢谢你。
采纳答案by Jon
The basic idea to make this comparison would be to use Array.split
to get arrays of parts from the input strings and then compare pairs of parts from the two arrays; if the parts are not equal we know which version is smaller.
进行这种比较的基本思想是使用Array.split
从输入字符串中获取部件数组,然后比较两个数组中的部件对;如果零件不相等,我们就知道哪个版本更小。
There are a few of important details to keep in mind:
有一些重要的细节需要牢记:
- How should the parts in each pair be compared? The question wants to compare numerically, but what if we have version strings that are not made up of just digits (e.g. "1.0a")?
- What should happen if one version string has more parts than the other? Most likely "1.0" should be considered less than "1.0.1", but what about "1.0.0"?
- 应该如何比较每对中的零件?问题想用数字进行比较,但是如果我们有不只由数字组成的版本字符串(例如“1.0a”)怎么办?
- 如果一个版本字符串的部分比另一个多,会发生什么?最有可能的“1.0”应该被认为小于“1.0.1”,但是“1.0.0”呢?
Here's the code for an implementation that you can use directly (gist with documentation):
这是您可以直接使用的实现代码(带有文档的要点):
function versionCompare(v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
}
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
This version compares parts naturally, does not accept character suffixes and considers "1.7" to be smaller than "1.7.0". The comparison mode can be changed to lexicographical and shorter version strings can be automatically zero-padded using the optional third argument.
这个版本比较自然,不接受字符后缀,认为“1.7”小于“1.7.0”。比较模式可以更改为字典序,并且可以使用可选的第三个参数自动填充较短的版本字符串。
There is a JSFiddle that runs "unit tests" here; it is a slightly expanded version of ripper234's work(thank you).
有一个 JSFiddle在这里运行“单元测试” ;它是ripper234 作品的稍微扩展版本(谢谢)。
Important note:This code uses Array.map
and Array.every
, which means that it will not run in IE versions earlier than 9. If you need to support those you will have to provide polyfills for the missing methods.
重要提示:此代码使用Array.map
and Array.every
,这意味着它不会在早于 9 的 IE 版本中运行。如果您需要支持那些,则必须为缺少的方法提供 polyfill。
回答by Mohammed Akdim
semver
服务器
The semantic version parser used by npm.
npm 使用的语义版本解析器。
$ npm install semver
$ npm 安装服务器
var semver = require('semver');
semver.diff('3.4.5', '4.3.7') //'major'
semver.diff('3.4.5', '3.3.7') //'minor'
semver.gte('3.4.8', '3.4.7') //true
semver.ltr('3.4.8', '3.4.7') //false
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
var versions = [ '1.2.3', '3.4.5', '1.0.2' ]
var max = versions.sort(semver.rcompare)[0]
var min = versions.sort(semver.compare)[0]
var max = semver.maxSatisfying(versions, '*')
Semantic Versioning Link:
https://www.npmjs.com/package/semver#prerelease-identifiers
语义版本控制链接:https:
//www.npmjs.com/package/semver#prerelease-identifiers
回答by Joe
// Return 1 if a > b
// Return -1 if a < b
// Return 0 if a == b
function compare(a, b) {
if (a === b) {
return 0;
}
var a_components = a.split(".");
var b_components = b.split(".");
var len = Math.min(a_components.length, b_components.length);
// loop while the components are equal
for (var i = 0; i < len; i++) {
// A bigger than B
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
return 1;
}
// B bigger than A
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
return -1;
}
}
// If one's a prefix of the other, the longer one is greater.
if (a_components.length > b_components.length) {
return 1;
}
if (a_components.length < b_components.length) {
return -1;
}
// Otherwise they are the same.
return 0;
}
console.log(compare("1", "2"));
console.log(compare("2", "1"));
console.log(compare("1.0", "1.0"));
console.log(compare("2.0", "1.0"));
console.log(compare("1.0", "2.0"));
console.log(compare("1.0.1", "1.0"));
回答by LeJared
This very small, yet very fast compare function takes version numbers of any lengthand any number size per segment.
这个非常小但非常快的比较函数采用任何长度和任何数字大小的每个段的版本号。
Return values:
- a number < 0
if a < b
- a number > 0
if a > b
- 0
if a = b
返回值:
-< 0
如果 a < b
为数字 -> 0
如果 a > b为数字
-0
如果 a = b
So you can use it as compare function for Array.sort();
所以你可以将它用作Array.sort(); 的比较函数;
EDIT:Bugfixed Version stripping trailing zeros to recognize "1" and "1.0.0" as equal
编辑:修正错误的版本去除尾随零以将“1”和“1.0.0”识别为相等
function cmpVersions (a, b) {
var i, diff;
var regExStrip0 = /(\.0+)+$/;
var segmentsA = a.replace(regExStrip0, '').split('.');
var segmentsB = b.replace(regExStrip0, '').split('.');
var l = Math.min(segmentsA.length, segmentsB.length);
for (i = 0; i < l; i++) {
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
if (diff) {
return diff;
}
}
return segmentsA.length - segmentsB.length;
}
// TEST
console.log(
['2.5.10.4159',
'1.0.0',
'0.5',
'0.4.1',
'1',
'1.1',
'0.0.0',
'2.5.0',
'2',
'0.0',
'2.5.10',
'10.5',
'1.25.4',
'1.2.15'].sort(cmpVersions));
// Result:
// ["0.0.0", "0.0", "0.4.1", "0.5", "1.0.0", "1", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"]
回答by user123444555621
Taken from http://java.com/js/deployJava.js:
取自http://java.com/js/deployJava.js:
// return true if 'installed' (considered as a JRE version string) is
// greater than or equal to 'required' (again, a JRE version string).
compareVersions: function (installed, required) {
var a = installed.split('.');
var b = required.split('.');
for (var i = 0; i < a.length; ++i) {
a[i] = Number(a[i]);
}
for (var i = 0; i < b.length; ++i) {
b[i] = Number(b[i]);
}
if (a.length == 2) {
a[2] = 0;
}
if (a[0] > b[0]) return true;
if (a[0] < b[0]) return false;
if (a[1] > b[1]) return true;
if (a[1] < b[1]) return false;
if (a[2] > b[2]) return true;
if (a[2] < b[2]) return false;
return true;
}
回答by Viktor
Couldn't find a function doing what I wanted here. So I wrote my own. This is my contribution. I hope someone find it useful.
找不到在这里做我想做的功能。所以我写了我自己的。这是我的贡献。我希望有人觉得它有用。
Pros:
优点:
Handles version strings of arbitrary length. '1' or '1.1.1.1.1'.
Defaults each value to 0 if not specified. Just because a string is longer doesn't mean it's a bigger version. ('1' should be the same as '1.0' and '1.0.0.0'.)
Compare numbers not strings. ('3'<'21' should be true. Not false.)
Don't waste time on useless compares in the loop. (Comparing for ==)
You can choose your own comparator.
处理任意长度的版本字符串。“1”或“1.1.1.1.1”。
如果未指定,则将每个值默认为 0。仅仅因为一个字符串更长并不意味着它是一个更大的版本。(“1”应该与“1.0”和“1.0.0.0”相同。)
比较数字而不是字符串。('3'<'21' 应该是真的。不是假的。)
不要在循环中无用的比较上浪费时间。(比较==)
您可以选择自己的比较器。
Cons:
缺点:
- It does not handle letters in the version string. (I don't know how that would even work?)
- 它不处理版本字符串中的字母。(我不知道这甚至会如何工作?)
My code, similar to the accepted answer by Jon:
我的代码,类似于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);
}
Examples:
例子:
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
回答by Arthur Araújo
Simple and short function:
简单而简短的功能:
function isNewerVersion (oldVer, newVer) {
const oldParts = oldVer.split('.')
const newParts = newVer.split('.')
for (var i = 0; i < newParts.length; i++) {
const a = parseInt(newParts[i]) || 0
const b = parseInt(oldParts[i]) || 0
if (a > b) return true
if (a < b) return false
}
return false
}
Tests:
测试:
isNewerVersion('1.0', '2.0') // true
isNewerVersion('1.0', '1.0.1') // true
isNewerVersion('1.0.1', '1.0.10') // true
isNewerVersion('1.0.1', '1.0.1') // false
isNewerVersion('2.0', '1.0') // false
isNewerVersion('2', '1.0') // false
isNewerVersion('2.0.0.0.0.1', '2.1') // true
isNewerVersion('2.0.0.0.0.1', '2.0') // false
回答by Noxin
Forgive me if this idea already been visited in a link I have not seen.
如果这个想法已经在我没有看到的链接中被访问过,请原谅我。
I have had some success with conversion of the parts into a weighted sum like so:
我在将部分转换为加权总和方面取得了一些成功,如下所示:
partSum = this.major * Math.Pow(10,9);
partSum += this.minor * Math.Pow(10, 6);
partSum += this.revision * Math.Pow(10, 3);
partSum += this.build * Math.Pow(10, 0);
Which made comparisons very easy (comparing a double). Our version fields are never more than 4 digits.
这使得比较非常容易(比较双精度)。我们的版本字段永远不会超过 4 位数字。
7.10.2.184 -> 7010002184.0
7.11.0.1385 -> 7011001385.0
I hope this helps someone, as the multiple conditionals seem a bit overkill.
我希望这对某人有所帮助,因为多个条件似乎有点矫枉过正。
回答by vanowm
Here is another short version that works with any number of sub versions, padded zeros and even numbers with letters (1.0.0b3)
这是另一个短版本,适用于任意数量的子版本、填充零甚至带字母的数字 (1.0.0b3)
function compareVer(a, b)
{
//treat non-numerical characters as lower version
//replacing them with a negative number based on charcode of each character
function fix(s)
{
return "." + (s.toLowerCase().charCodeAt(0) - 2147483647) + ".";
}
a = ("" + a).replace(/[^0-9\.]/g, fix).split('.');
b = ("" + b).replace(/[^0-9\.]/g, fix).split('.');
var c = Math.max(a.length, b.length);
for (var i = 0; i < c; i++)
{
//convert to integer the most efficient way
a[i] = ~~a[i];
b[i] = ~~b[i];
if (a[i] > b[i])
return 1;
else if (a[i] < b[i])
return -1;
}
return 0;
}
Output:
输出:
0: a = b
0: a = b
1: a > b
1: a > b
-1: a < b
-1: a < b
1.0.0.0.0.0 = 1.0
1.0 < 1.0.1
1.0b1 < 1.0
1.0a < 1.0b
1.1 > 1.0.1b
1.1alpha < 1.1beta
1.1rc1 > 1.1beta
1.0001 > 1.00000.1.0.0.0.01
/*use strict*/
function compareVer(a, b)
{
//treat non-numerical characters as lover version
//replacing them with a negative number based on charcode of each character
function fix(s)
{
return "." + (s.toLowerCase().charCodeAt(0) - 2147483647) + ".";
}
a = ("" + a).replace(/[^0-9\.]/g, fix).split('.');
b = ("" + b).replace(/[^0-9\.]/g, fix).split('.');
var c = Math.max(a.length, b.length);
for (var i = 0; i < c; i++)
{
//convert to integer the most efficient way
a[i] = ~~a[i];
b[i] = ~~b[i];
if (a[i] > b[i])
return 1;
else if (a[i] < b[i])
return -1;
}
return 0;
}
var type = {
"-1": " < ",
"0": " = ",
"1": " > "
};
var list = [
["1.0.0.0.0.0", "1.0"],
["1.0", "1.0.1"],
["1.0b1", "1.0"],
["1.0a", "1.0b"],
["1.1", "1.0.1b"],
["1.1alpha", "1.1beta"],
["1.1rc1", "1.1beta"],
["1.0001", "1.00000.1.0.0.0.01"]
];
for(var i = 0; i < list.length; i++)
{
console.log(list[i][0] + type[compareVer(list[i][0], list[i][1])] + list[i][1]);
}
回答by pery mimon
2017 answer:
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;
}
Simplest code for modern browsers:
现代浏览器的最简单代码:
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;
}
The idea here is to compare numbers but in the form of string. to make the comparison work the two strings must be at the same length. so:
这里的想法是比较数字,但以字符串的形式。为了进行比较,两个字符串的长度必须相同。所以:
"123" > "99"
become "123" > "099"
padding the short number "fix" the comparison
"123" > "99"
成为"123" > "099"
填充短数字“修复”比较
Here I padding each part with zeros to lengths of 10. then just use simple string compare for the answer
在这里,我用零填充每个部分到 10 的长度。然后只需使用简单的字符串比较作为答案
Example :
例子 :
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