Reputation: 1681
How to write a piece of code to compare some versions strings and get the newest?
For example strings like: '0.1', '0.2.1', '0.44'
.
Upvotes: 136
Views: 31704
Reputation: 1515
I had the same problem, I wanted a Gem-less version comparator, came up with this:
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
Upvotes: -1
Reputation: 5949
If you need to check pessimistic version constraints, you can use Gem::Dependency like this:
Gem::Dependency.new('', '~> 1.4.5').match?('', '1.4.6beta4')
Upvotes: 43
Reputation: 95242
Gem::Version
is the easy way to go here:
%w<0.1 0.2.1 0.44>.map {|v| Gem::Version.new v}.max.to_s
=> "0.44"
Upvotes: 9
Reputation: 146053
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')]
Upvotes: 22
Reputation: 6872
If you want to do it by hand without using any gems, something like the following should work, though it's a little perly looking.
versions = [ '0.10', '0.2.1', '0.4' ]
versions.map{ |v| (v.split '.').collect(&:to_i) }.max.join '.'
Essentially, you turn each version string in to an array of integers and then use the array comparison operator. You could break out the component steps to get something a little easier to follow if this is going in code somebody will need to maintain.
Upvotes: 5
Reputation: 67750
I would do
a1 = v1.split('.').map{|s|s.to_i}
a2 = v2.split('.').map{|s|s.to_i}
Then you can do
a1 <=> a2
(and probably all the other "usual" comparisons).
...and if you want a <
or >
test, you can do e.g.
(a1 <=> a2) < 0
or do some more function wrapping if you're so inclined.
Upvotes: 11
Reputation: 59299
You can use the Versionomy
gem (available at 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
Upvotes: 15