如何比较Ruby中的版本?

use*_*895 114 ruby

如何编写一段代码来比较一些版本的字符串并获得最新的?

例如字符串:'0.1', '0.2.1', '0.44'.

gro*_*ser 218

Gem::Version.new('0.4.1') > Gem::Version.new('0.10.1')
Run Code Online (Sandbox Code Playgroud)

  • `Gem :: Version ...`语法让我觉得我需要安装一个gem.但这不是必需的. (13认同)
  • @uliwitness不是Ruby 1.x vs 2.x; 它是1.8.x vs 1.9+.Ruby到1.8.x默认情况下不包含rubygems; 你需要一个`require'rubygems'来访问`Gem`命名空间.然而,从1.9开始,它会自动包含在内. (6认同)
  • `Gem :: Dependency.new(nil,'〜> 1.4.5').match?(nil,'1.4.6beta4')` (5认同)

lev*_*lex 33

如果需要检查悲观版本约束,可以像这样使用Gem :: Dependency:

Gem::Dependency.new('', '~> 1.4.5').match?('', '1.4.6beta4')
Run Code Online (Sandbox Code Playgroud)


Dig*_*oss 19

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')]
Run Code Online (Sandbox Code Playgroud)

  • 赞成简洁的解决方案,不需要安装宝石. (7认同)
  • 就像这里的其他一些答案一样,看起来你正在进行字符串比较而不是数字,这在比较'0.10'和'0.4'等版本时会引起问题. (3认同)
  • 值得的是:`vers =(1..3000000).map {| x | "0.0#{X}."}; 'ok'把Time.now; vers.map {| V | ComparableVersion.new(v)} .sort.first; 把Time.now#24秒2013-10-29 13:36:09 -0700 2013-10-29 13:36:33 -0700 => nil把Time.now; vers.map {| V | Gem :: Version.new(v)} .sort.first; 放置Time.now#41秒2013-10-29 13:36:53 -0700 2013-10-29 13:37:34 -0700`代码blob让它变得丑陋,但基本上,使用这个vs Gem :: Version是大约快两倍. (2认同)

not*_*oop 15

你可以使用Versionomygem(可在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
Run Code Online (Sandbox Code Playgroud)

  • "不要重新发明轮子".因为它很简单并不意味着程序员没有把工作和思想融入其中.使用宝石,阅读代码,并从中学习 - 继续前进更大更好的事物! (8认同)
  • 我已经看过了,但要求我用2颗宝石来做一件非常简单的事情.我想用它作为最后的选择. (4认同)

Car*_*icz 10

我会做

a1 = v1.split('.').map{|s|s.to_i}
a2 = v2.split('.').map{|s|s.to_i}
Run Code Online (Sandbox Code Playgroud)

那你可以做

a1 <=> a2
Run Code Online (Sandbox Code Playgroud)

(可能还有所有其他"常规"比较).

...如果你想要一个<>测试,你可以做例如

(a1 <=> a2) < 0
Run Code Online (Sandbox Code Playgroud)

如果你这么倾向,还是做一些功能包装.

  • 我在这个解决方案中发现的问题是它返回"1.2.0"大于"1.2" (4认同)

Mar*_*eed 8

Gem::Version 这是一个简单的方法:

%w<0.1 0.2.1 0.44>.map {|v| Gem::Version.new v}.max.to_s
=> "0.44"
Run Code Online (Sandbox Code Playgroud)

  • 这似乎已在最新的Gem :: Version中得到修复.现在正确报告0.44高于0.5. (2认同)

Joh*_*and 5

如果您希望不使用任何宝石而手工完成此任务,那么如下所示的方法应该可以工作,尽管看起来有些麻烦。

versions = [ '0.10', '0.2.1', '0.4' ]
versions.map{ |v| (v.split '.').collect(&:to_i) }.max.join '.'
Run Code Online (Sandbox Code Playgroud)

本质上,您将每个版本字符串都转换为整数数组,然后使用数组比较运算符。如果这是某些人需要维护的代码,则可以拆分组件步骤以使操作更容易一些。