红宝石中的版本排序(使用alphas,beta等)

Cha*_*ert 14 ruby sorting natural-sort version-sort

如何在Ruby中对版本列表进行排序?我见过关于自然排序的东西,但这是一个超越它的一步.

输入是一堆像这样的字符串:

input = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3']
Run Code Online (Sandbox Code Playgroud)

我几乎可以用天然宝石做到这一点:

require 'naturally'
Naturally.sort(input)
=> ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b12", "10.0.0b3"]    
Run Code Online (Sandbox Code Playgroud)

问题:10.0.0b3在10.0.0b12之后排序; 10.0.0b3应该是第一个.

有人有办法吗?其他语言也很有帮助!

ste*_*lag 26

Ruby附带了Gem类,它知道版本:

ar = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3']

p ar.sort_by { |v| Gem::Version.new(v) }
# => ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b3", "10.0.0b12"]
Run Code Online (Sandbox Code Playgroud)

  • 尼斯.对于它的价值 - 看起来这只是按字母顺序处理"alpha"和"beta".也就是说,`['9.0.10rc2','9.0.10','9.0.10rc1','9.0.10a','9.0.10test']`产生`["9.0.10a","9.0.10rc1" ,"9.0.10rc2","9.0.10test","9.0.10"]`.应该足够了,因为"alpha/beta/pre-release/rc/release"无论如何都会按字母顺序流动,但如果你的数据偏离太远,可能会很古怪. (2认同)

Dre*_*awn 5

如果您将此解释为“按每个数字段排序”,那么您将使用以下内容处理上面的示例输入:

input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last)
=> ["9_0", "9_1", "10_0b3", "10_0b12"]
Run Code Online (Sandbox Code Playgroud)

那是,

  • 对于每个值,例如 10_0b3
  • 拆分任意长度的非数字字符,例如 ["10","0","3"]
  • 将每个数字段转换为整数,例如 [10,0,3]
  • 使用原始输入压缩,产生 [[[10, 0, 12], "10_0b12"], [[10, 0, 3], "10_0b3"], [[9, 0], "9_0"], [[9, 1], "9_1"]]
  • 排序,凭借 [10,0,3] < [10,0,12]
  • 获取每个元素的最后一个值,这是每个处理过的可排序值对应的原始输入值

现在授予,这仍然是非常自定义的——不会处理像“9_0a”和“9_0b”这样简单的版本号,两者都将显示为 [9,0]——所以你可能需要进一步调整它,但是希望这会让你走上一条可行的道路。

编辑:上面的示例输入已更改,因此我更改了正则表达式以确保数字匹配是贪婪的,并且它仍然有效:

irb(main):018:0> input = ['10.0.0b12', '10.0.0b3', '9.0.10', '9.0.3']
=> ["10.0.0b12", "10.0.0b3", "9.0.10", "9.0.3"]
irb(main):025:0> input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last)
=> ["9.0.3", "9.0.10", "10.0.0b3", "10.0.0b12"]
Run Code Online (Sandbox Code Playgroud)