如何比较任意版本号?
有人有在 JavaScript 中比较两个版本号的代码吗?我只想要简单的版本比较(例如 "1.0"
与 "1.5.6"
),并且它应该适用于数字或字符串。它可以忽略尾随的 beta 标识符,例如 "1.5.6b4"
,但可以期望字符串格式良好。该函数应像普通 cmp 函数一样返回一个有符号整数。
function cmpVersion(a, b)
return less than one if a < b
return 0 if a == b
return greater than one if a > b
我有一个答案,但会选择一个比我自己的更好或更优雅的解决方案。
(我用它来比较 jQuery.browser.version 数字,但答案将更广泛适用)
Does anyone have code to compare two version numbers in JavaScript? I just want simple version comparisons (e.g. "1.0"
vs "1.5.6"
), and it should work with numbers or strings. It can ignore trailing beta identifiers like "1.5.6b4"
, but can otherwise expect the strings to be well-formed. The function should return a signed integer like a normal cmp function.
function cmpVersion(a, b)
return less than one if a < b
return 0 if a == b
return greater than one if a > b
I have an answer, but will choose a better or more elegant solution over my own.
(I am using this to compare jQuery.browser.version
numbers, but the answer will be more widely applicable)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
如果您不关心 .5.6,请使用 parseInt
既然你说你关心小版本:
If you do not care about the .5.6, use parseInt
Since you said you care about the minor versions:
如果版本大于或等于最小版本,则此函数返回 true。当版本为字符串时,假定 1.0 大于 1。当它们是数字时,就表示它们是相同的。如果您想让两种类型返回相同的值,那么您需要将数字转换为字符串,这也很容易。或者您可以修改字符串条件来检查较长的版本号是否全部尾随零,例如 1.1 与 1.1.0.0.0.0。第二个全是尾随零
This function returns true if the version is greater than or equal to the minimum version. Assumes 1.0 is greater than 1 when versions are strings. When they are numbers it says they are the same. If you want to have both types return the same then you need to convert the numbers to strings which is also easy. or you can modify the string condition to check if the longer version number has all trailing zeros like 1.1 vs 1.1.0.0.0.0. the second one is all trailing zeros
该函数处理:
cmpVersion("1.0", 1)
返回0
)alpha
、<代码>b、pre4
等This function handles:
cmpVersion("1.0", 1)
returns0
)alpha
,b
,pre4
, etc如果您想完全正确,请查看 PEP386 上的讨论,尤其是标题“新版本控制算法”。
否则看起来你的答案很好。
If you want to be fully correct, take a look at the discussion on PEP386, especially the heading “the new versioning algorithm”.
Otherwise it seems like your answer is pretty good.
npm 使用很好的语法来比较版本,您可以在这里获取相同的模块: https://github.com/ isaacs/node-semver
支持以下范围样式:
1.2.3
特定版本。当没有其他事可以做的时候。请注意,构建元数据仍然被忽略,因此1.2.3+build2012
将满足此范围。>1.2.3
大于特定版本。<1.2.3
小于特定版本。如果版本范围上没有预发布标签,则也不会允许预发布版本,即使这些版本在技术上“小于”。>=1.2.3
大于或等于。请注意,预发布版本不等于其“正常”版本,因此1.2.3-beta
不会满足此范围,但2.3.0-beta
可以。<=1.2.3
小于或等于。在这种情况下,允许预发布版本,因此1.2.3-beta
就可以满足。1.2.3 - 2.3.4
:=>=1.2.3 <=2.3.4
~1.2.3
:=>=1.2.3-0 <1.3.0-0
“相当接近 1.2.3”。使用波形符运算符时,也支持预发布版本,但下一个有效数字的预发布将无法令人满意,因此1.3.0-beta
将不满足~1.2.3
代码>.^1.2.3
:=>=1.2.3-0 <2.0.0-0
“与 1.2.3 兼容”。使用脱字符号运算符时,指定版本(包括预发行版)中的任何内容都将受到支持,直到但不包括下一个主要版本(或其预发行版)。1.5.1
将满足^1.2.3
,而1.2.2
和2.0.0-beta
则不会。^0.1.3
:=>=0.1.3-0 <0.2.0-0
“与 0.1.3 兼容”。 0.xx 版本很特殊:第一个非零组件表示潜在的重大更改,这意味着插入符号运算符与从指定版本开始具有相同第一个非零组件的任何版本相匹配。^0.0.2
:==0.0.2
"只有 0.0.2 版本才被认为是兼容的"~1.2
:=> ;=1.2.0-0 <1.3.0-0
"以 1.2 开头的任何版本"^1.2
:=>=1.2.0-0 <2.0.0-0
“与 1.2 兼容的任何版本”1.2.x
:=>=1.2.0 -0 <1.3.0-0
"以 1.2 开头的任何版本"~1
:=>=1.0.0-0 <2.0.0-0
"以 1 开头的任何版本"^1
:=>=1.0.0-0 <2.0.0-0
"与 1 兼容的任何版本"1.x
:=>=1.0.0-0 <2.0.0-0
"以 1 开头的任何版本"范围可以用空格(暗示“和”)或
||
(暗示“或”)。npm uses a nice syntax to compare versions and you can get the same module here: https://github.com/isaacs/node-semver
The following range styles are supported:
1.2.3
A specific version. When nothing else will do. Note that build metadata is still ignored, so1.2.3+build2012
will satisfy this range.>1.2.3
Greater than a specific version.<1.2.3
Less than a specific version. If there is no prerelease tag on the version range, then no prerelease version will be allowed either, even though these are technically "less than".>=1.2.3
Greater than or equal to. Note that prerelease versions are NOT equal to their "normal" equivalents, so1.2.3-beta
will not satisfy this range, but2.3.0-beta
will.<=1.2.3
Less than or equal to. In this case, prerelease versions ARE allowed, so1.2.3-beta
would satisfy.1.2.3 - 2.3.4
:=>=1.2.3 <=2.3.4
~1.2.3
:=>=1.2.3-0 <1.3.0-0
"Reasonably close to 1.2.3". When using tilde operators, prerelease versions are supported as well, but a prerelease of the next significant digit will NOT be satisfactory, so1.3.0-beta
will not satisfy~1.2.3
.^1.2.3
:=>=1.2.3-0 <2.0.0-0
"Compatible with 1.2.3". When using caret operators, anything from the specified version (including prerelease) will be supported up to, but not including, the next major version (or its prereleases).1.5.1
will satisfy^1.2.3
, while1.2.2
and2.0.0-beta
will not.^0.1.3
:=>=0.1.3-0 <0.2.0-0
"Compatible with 0.1.3". 0.x.x versions are special: the first non-zero component indicates potentially breaking changes, meaning the caret operator matches any version with the same first non-zero component starting at the specified version.^0.0.2
:==0.0.2
"Only the version 0.0.2 is considered compatible"~1.2
:=>=1.2.0-0 <1.3.0-0
"Any version starting with 1.2"^1.2
:=>=1.2.0-0 <2.0.0-0
"Any version compatible with 1.2"1.2.x
:=>=1.2.0-0 <1.3.0-0
"Any version starting with 1.2"~1
:=>=1.0.0-0 <2.0.0-0
"Any version starting with 1"^1
:=>=1.0.0-0 <2.0.0-0
"Any version compatible with 1"1.x
:=>=1.0.0-0 <2.0.0-0
"Any version starting with 1"Ranges can be joined with either a space (which implies "and") or a
||
(which implies "or").我制作了以下函数,它支持尾随字母、前导零……(参见下面的示例):
所以,有几个例子:
如果您不需要支持前导零,这里有一个更简单的替代方案:
快速更新:后来我注意到第一个函数将“1.2”排序在“1.10”之前,这是明显错误的。此外,“重要的前导零”是棘手且不明确的(无论是解释还是实现),语义版本控制明确避免它们。因此,我认为第二个功能应该始终是首选。
更新2:但是第二个函数将“1.2a”排序在“1.1”之前...我认为没有“一应俱全”的函数...根据以下内容选择“更合适”的函数您的用例,或者更好的是,如果可以的话,按日期排序。
更新3:修改了第一个函数以正确处理重要情况“1.2 / 1.10”。作为副作用,它打破了不那么重要的情况“1.02 / 1.1”,显然它现在是唯一的警告(也许它可以被修复,但我不确定它是否值得)。因此,我现在推荐固定的第一个函数。
I have crafted the following function, which supports trailing letters, leading zeroes… (see examples below):
So, a few examples:
If you don't need to support leading zeroes, here is a simpler alternative:
Quick update: I noticed afterwards that the first function sorts "1.2" before "1.10", which is blatantly wrong. Also, the "significant leading zeroes" are tricky and ambiguous (both to interpret and to implement), and Semantic Versioning explicitly avoids them. Therefore, I think the second function should always be preferred.
Update 2: But the second function sorts "1.2a" before "1.1"... I think there is just no "one fits all" function... Pick the "more appropriate" function according to your use case, or better, rather sort by date if you can.
Update 3: Modified the first function to handle correctly the important case "1.2 / 1.10". As a side effect, it breaks the not-so-important case "1.02 / 1.1", and apparently it's now the only caveat (maybe it could be fixed, but I'm not sure it's worth it). Therefore, I'm now recommending the fixed, first function.
我已经将我的内容重构为尽可能简洁。它不检查尾随零,但适用于任何长度的内部版本号(例如,major、major.minor、major.minor.build)。
基本上,首先我从每个版本字符串中创建了一个新数组,以便我可以单独比较每个数字。然后在 for 循环中,我选择最长版本字符串的长度(如果它们长度相等,则选择第一个版本字符串的长度)。
if 语句检查 a 中是否有数字但 b 中没有,或者对于相应的占位符,a 的数字是否大于 b 的数字,在这种情况下,它将返回“小于一”。
同样,else 语句检查 b 中是否有数字但 a 中没有,或者 b 的数字是否大于相应位值的 a 的数字,在这种情况下,它将返回“大于一” 。
最后一个 return 0 语句是一个包罗万象的语句,如果版本字符串相等,我们的函数就会到达它。
I've refactored mine down to be as concise as I can make it. It does not have the check for trailing zeroes but will work for build numbers of any length (e.g. major, major.minor, major.minor.build).
Basically, first I created a new array out of each version string so that I can compare each digit individually. Then in the for loop, I choose the length of the longest version string (or the length of the first version string if they're of equal length).
The if statement checks to see if there is a digit in a but not in b or if the digit of a is greater than the digit of b for a corresponding placeholder, in which case it will return 'less than one'.
As well, the else statement checks to see if there is a digit in b but not in a or if the digit of b is greater than the digit of a for a corresponding place value, in which case it will return 'greater than one'.
The last return 0 statement is a catch-all, which our function will get to if the version strings are equal.