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
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
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.
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.
It's very easy to compare arrays in ruby, assuming the native <=> comparison works for every element of the array. You could do something like this, if all your arrays were numerics separated by . (or using the natural-order comparison library mentioned above, to support version components like 1a25):
#!/usr/bin/ruby
versions = ["1.2", "1.2", "1.2.3", "0.1", "0.2.1", "0.44"]
# This def taken from http://david-burger.blogspot.com/2008/09/generating-combinations-in-ruby-and_21.html
def generate_combinations(array, r)
n = array.length
indices = (0...r).to_a
final = (n - r...n).to_a
while indices != final
yield indices.map {|k| array[k]}
i = r - 1
while indices[i] == n - r + i
i -= 1
end
indices[i] += 1
(i + 1...r).each do |j|
indices[j] = indices[i] + j - i
end
end
yield indices.map {|k| array[k]}
end
# This is the real 'magic' - http://ruby-doc.org/core/classes/Array.html#M002204
def version_compare(first, second)
return first.split('.') <=> second.split('.')
end
def format_comparison(first, second)
compared = version_compare(first,second)
relation = case compared
when 0: "equal to"
when 1: "greater than"
when -1: "less than"
end
return "#{first} is #{relation} #{second}"
end
generate_combinations(versions, 2) do |pair|
puts format_comparison(pair[0], pair[1])
puts format_comparison(pair[1], pair[0])
end
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')]