我正在使用一些想要包含模块的软件,但仅适用于大于“2.1.3”的版本。正在使用的代码在版本“2.1.10”处分解,在字符串比较中被认为小于“2.1.3”。什么是正确比较版本号的最优雅方式?
答案 0 :(得分:2)
自然的第一步是拆分版本"数字"到数字组件:
v1 = '2.1.10'.split('.').map(&:to_i) # [ 2, 1, 10 ]
v2 = '2.1.3'.split('.').map(&:to_i) # [ 2, 1, 3 ]
然后请注意,Array#<=>
会逐个元素地对数组进行比较,以便您可以使用它来为数组提供快速的“<
实现”。您可以使用<=>
将补丁#<
和#>
方法添加到数组中,或者直接进行内联:
if (v1 <=> v2) < 0
# v1 < v2
elsif (v1 <=> v2) > 0
# v1 > v2
else
# v1 == v2
end
指定 <=>
返回-1
,0
或+1
,以便您可以使用
if (v1 <=> v2) == -1
# v1 < v2
elsif (v1 <=> v2) == 1
# v1 > v2
else
# v1 == v2
end
太;我更喜欢第一个版本,因为< 0
和> 0
对意图更具启发性。
您可能希望隐藏某个方法背后的所有内容,或者甚至可能将猴子修补程序String
隐藏起来以获得版本比较方法。
以上也意味着2.1
的版本号比2.1.11
更低,因此您不必担心拥有相同数量的组件。
我假设您正在使用其组件为十进制数的版本。
答案 1 :(得分:1)
我会将Versionomy Gem用于此类任务,特别是因为它还处理RC,alpha和beta版本等边缘情况:
v1 = Versionomy.create(:major => 1, :minor => 3, :tiny => 2)
v2 = Versionomy.parse('1.4a3')
v3 = Versionomy.parse('1.4.0b2')
v2 > v1 # => true
v3 > v2 # => true
答案 2 :(得分:1)
这是另一种方式:
<强>代码强>
class Version
include Comparable
attr_reader :v
def initialize(v)
@v = v
end
def <=>(ov)
pad_size = [v.size, ov.v.size].max
convert(pad_size) <=> ov.convert(pad_size)
end
def convert(pad_size)
v.gsub(/(^|\.)(\d+)/) { "#{$1}#{$2.rjust(pad_size,'0')}#{$3}" }
end
end
示例强>
v0 = Version.new("2.1.02.3")
#=> #<Version:0x007ff36a1055d0 @v="2.1.23.3">
v1 = Version.new("10.9.4.22")
#=> #<Version:0x007ff36988fea0 @v="10.9.4.22">
v2 = Version.new("1.11.4.1")
#=> #<Version:0x007ff369875b18 @v="1.11.4.1">
v3 = Version.new("10.9.4.22")
#=> #<Version:0x007ff369864570 @v="10.9.4.22">
v0 <=> v1 #=> -1
v0 <=> v2 #=> 1
v1 <=> v2 #=> 1
v1 <=> v3 #=> 0
v0 < v1 #=> true
[v0, v1, v2, v3].sort
#=> [#<Version:0x007ff36996ba68 @v="1.11.4.1">,
# #<Version:0x007ff369990868 @v="2.1.02.3">,
# #<Version:0x007ff36997b418 @v="10.9.4.22">,
# #<Version:0x007ff369952838 @v="10.9.4.22">]
v0 < v1
取决于include Comparable
在场。 (见μ的评论。)
<强>解释强>
v0 = Version.new("2.1.02.3")
v1 = Version.new("10.9.4.22")
pad_size = [v0.v.size, v1.v.size].max
#=> [8, 9].max => 9
v0.convert(9)
#=> "000000002.000000001.000000002.000000003"
v1.convert(9)
#=> "000000010.000000009.000000004.000000022"
因此,v0 <=> v1 #=> -1
。
答案 3 :(得分:0)
有用于比较版本号的库,其中一个包含在RubGems(它是Ruby stdlib的一部分)中,但是,对于简单版本号,如问题中的那些,只需拆分版本字符串,将其转换为数字,并依赖于Ruby中的数组按字典顺序排序的事实就足够了:
v1 = '2.1.3'.split('.').map(&:to_i)
v2 = '2.1.10'.split('.').map(&:to_i)
v1 <=> v2
# => -1
答案 4 :(得分:-3)
在我写上述问题时,我想出了以下内容:
"2.1.10".split('.')[0,3].join('').to_i >= "2.1.3".split('.')[0,3].join('').to_i
拆分和重新加入允许限制前三个位置,因为有一个可选的第四位用于描述性字符串
答案 5 :(得分:-4)
一开始就试试这个:
if RUBY_VERSION <= '2.1.3'<br>
puts("Upgrade to version newer than 2.1.3")<br>
end