【发布时间】:2010-01-12 18:10:47
【问题描述】:
如何编写一段代码来比较一些版本的字符串并获取最新的?
例如像这样的字符串:'0.1', '0.2.1', '0.44'。
【问题讨论】:
-
我需要比较悲观的版本约束,但我不想依赖 RubyGems 来做这件事,所以我写了一个简单的
Version类来满足我的一切需求:@987654321 @
标签: ruby
如何编写一段代码来比较一些版本的字符串并获取最新的?
例如像这样的字符串:'0.1', '0.2.1', '0.44'。
【问题讨论】:
Version 类来满足我的一切需求:@987654321 @
标签: ruby
Gem::Version.new('0.4.1') > Gem::Version.new('0.10.1')
【讨论】:
Gem::Version... 语法让我觉得我需要安装一个 gem。但这不是必需的。
Gem::Dependency.new(nil, '~> 1.4.5').match?(nil, '1.4.6beta4')
require 'rubygems' 才能访问 Gem 命名空间。但是,从 1.9 开始,它会自动包含在内。
如果需要查看pessimistic version constraints,可以这样使用Gem::Dependency:
Gem::Dependency.new('', '~> 1.4.5').match?('', '1.4.6beta4')
【讨论】:
Gem::Dependency.new('', '~> 1.4.5').match?('', '1.4.6beta4')
class Version < Array
def initialize s
super(s.split('.').map { |e| e.to_i })
end
def < x
(self <=> x) < 0
end
def > x
(self <=> x) > 0
end
def == x
(self <=> x) == 0
end
end
p [Version.new('1.2') < Version.new('1.2.1')]
p [Version.new('1.2') < Version.new('1.10.1')]
【讨论】:
vers = (1..3000000).map{|x| "0.0.#{x}"}; 'ok' puts Time.now; vers.map{|v| ComparableVersion.new(v) }.sort.first; puts Time.now # 24 seconds 2013-10-29 13:36:09 -0700 2013-10-29 13:36:33 -0700 => nil puts Time.now; vers.map{|v| Gem::Version.new(v) }.sort.first; puts Time.now # 41 seconds 2013-10-29 13:36:53 -0700 2013-10-29 13:37:34 -0700 代码 blob 让它变得丑陋,但基本上,使用 this vs Gem::Version 大约快两倍。
您可以使用Versionomy gem(可在github 获取):
require 'versionomy'
v1 = Versionomy.parse('0.1')
v2 = Versionomy.parse('0.2.1')
v3 = Versionomy.parse('0.44')
v1 < v2 # => true
v2 < v3 # => true
v1 > v2 # => false
v2 > v3 # => false
【讨论】:
我愿意
a1 = v1.split('.').map{|s|s.to_i}
a2 = v2.split('.').map{|s|s.to_i}
那你就可以了
a1 <=> a2
(可能还有所有其他“通常”的比较)。
...如果你想要 < 或 > 测试,你可以做例如
(a1 <=> a2) < 0
如果你愿意,也可以做更多的函数包装。
【讨论】:
Gem::Version 是去这里的简单方法:
%w<0.1 0.2.1 0.44>.map {|v| Gem::Version.new v}.max.to_s
=> "0.44"
【讨论】:
如果您想在不使用任何宝石的情况下手动完成,则应该可以使用类似以下的方法,尽管它看起来有点过时。
versions = [ '0.10', '0.2.1', '0.4' ]
versions.map{ |v| (v.split '.').collect(&:to_i) }.max.join '.'
本质上,您将每个版本字符串转换为整数数组,然后使用array comparison operator。如果这是在有人需要维护的代码中进行,您可以分解组件步骤以使某些东西更容易遵循。
【讨论】:
我有同样的问题,我想要一个无宝石版本的比较器,想出了这个:
def compare_versions(versionString1,versionString2)
v1 = versionString1.split('.').collect(&:to_i)
v2 = versionString2.split('.').collect(&:to_i)
#pad with zeroes so they're the same length
while v1.length < v2.length
v1.push(0)
end
while v2.length < v1.length
v2.push(0)
end
for pair in v1.zip(v2)
diff = pair[0] - pair[1]
return diff if diff != 0
end
return 0
end
【讨论】: