ruby 中的版本排序(使用 alpha、beta 等)
Version sort (with alphas, betas, etc.) in ruby
如何对 Ruby 中的版本列表进行排序?我看过有关自然排序的内容,但这是更进一步的内容。
输入是一串这样的字符串:
input = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3']
我几乎可以用 naturally gem:
require 'naturally'
Naturally.sort(input)
=> ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b12", "10.0.0b3"]
问题:10.0.0b3 排在 10.0.0b12 之后; 10.0.0b3 应该是第一个。
有人有办法吗?其他语言也有帮助!
如果您将其解释为 "sort by each segment of digits",那么您将处理上面的示例输入:
input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last)
=> ["9_0", "9_1", "10_0b3", "10_0b12"]
即
- 对于每个值,例如
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"]
Ruby 附带 Gem class,它知道版本:
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"]
在特定情况下,您正在使用 NuGet 并希望根据来自 Ruby 代码的 NuGet 特有的版本控制方案进行解析、比较或排序,现在有:
https://rubygems.org/gems/nuget_versions
我专门为解决这个问题而创建的。 NuGet 的版本号有点奇怪,它们是 SemVer 的超集,也允许使用 4 个组件而不是 3 个。
如何对 Ruby 中的版本列表进行排序?我看过有关自然排序的内容,但这是更进一步的内容。
输入是一串这样的字符串:
input = ['10.0.0b12', '10.0.0b3', '10.0.0a2', '9.0.10', '9.0.3']
我几乎可以用 naturally gem:
require 'naturally'
Naturally.sort(input)
=> ["9.0.3", "9.0.10", "10.0.0a2", "10.0.0b12", "10.0.0b3"]
问题:10.0.0b3 排在 10.0.0b12 之后; 10.0.0b3 应该是第一个。
有人有办法吗?其他语言也有帮助!
如果您将其解释为 "sort by each segment of digits",那么您将处理上面的示例输入:
input.map{ |ver| ver.split(%r{[^\d]+}).map(&:to_i) }.zip(input).sort.map(&:last)
=> ["9_0", "9_1", "10_0b3", "10_0b12"]
即
- 对于每个值,例如
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"]
Ruby 附带 Gem class,它知道版本:
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"]
在特定情况下,您正在使用 NuGet 并希望根据来自 Ruby 代码的 NuGet 特有的版本控制方案进行解析、比较或排序,现在有:
https://rubygems.org/gems/nuget_versions
我专门为解决这个问题而创建的。 NuGet 的版本号有点奇怪,它们是 SemVer 的超集,也允许使用 4 个组件而不是 3 个。