如果你把它解释为“按照每个数字段排序”,那么下面的代码将处理你上面提供的示例输入:
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"]