如何在ruby中对字母数字数组进行排序

use*_*932 3 ruby sorting alphanumeric natural-sort

我如何在ruby中以字母数字方式对数组数据进行排序?

假设我的数组是 a = [test_0_1, test_0_2, test_0_3, test_0_4, test_0_5, test_0_6, test_0_7, test_0_8, test_0_9, test_1_0, test_1_1, test_1_2, test_1_3, test_1_4, test_1_5, test_1_6, test_1_7, test_1_8, test_1_9, test_1_10, test_1_11, test_1_12, test_1_13, test_1_14, ...........test_1_121...............]

我希望我的输出是:

.
.
.
test_1_121
.
.
.
test_1_14
test_1_13
test_1_12
test_1_11
test_1_10
test_1_9
test_1_8
test_1_7
test_1_6
test_1_5
test_1_4
test_1_3
test_1_2
test_1_1
test_0_10
test_0_9
test_0_8
test_0_7
test_0_6
test_0_5
test_0_4
test_0_3
test_0_2
test_0_1
Run Code Online (Sandbox Code Playgroud)

Joj*_*jje 7

用于对在任意位置包含非填充序列号的字符串进行排序的通用算法.

padding = 4
list.sort{|a,b|
  a,b = [a,b].map{|s| s.gsub(/\d+/){|m| "0"*(padding - m.size) + m } }
  a<=>b
}
Run Code Online (Sandbox Code Playgroud)

padding是您希望数字在比较期间具有的字段长度.如果字符串中找到的任何数字在比较之前将被填零,如果它包含少于"填充"数字的数字,则产生预期的排序顺序.

要产生user682932要求的结果,只需.reverse在排序块之后添加,这将自然排序(升序)翻转为降序.

通过字符串上的预循环,您当然可以动态地找到字符串列表中的最大位数,您可以使用它而不是硬编码某些任意填充长度,但这需要更多处理(更慢)和多一点代码.例如

padding = list.reduce(0){|max,s| 
  x = s.scan(/\d+/).map{|m|m.size}.max
  (x||0) > max ? x : max
}
Run Code Online (Sandbox Code Playgroud)


saw*_*awa 5

例如,如果您只是按字符串排序,则不会在'test_2'和'test_10'之间得到正确的顺序.所以:

sort_by{|s| s.scan(/\d+/).map{|s| s.to_i}}.reverse
Run Code Online (Sandbox Code Playgroud)


ctc*_*rry 2

您可以将块传递给排序函数以对其进行自定义排序。在您的情况下,您会遇到问题,因为您的数字没有用零填充,因此此方法对数字部分进行零填充,然后对它们进行排序,从而得到您想要的排序顺序。

a.sort { |a,b|
  ap = a.split('_')
  a = ap[0] + "%05d" % ap[1] + "%05d" % ap[2]
  bp = b.split('_')
  b = bp[0] + "%05d" % bp[1] + "%05d" % bp[2]
  b <=> a
}
Run Code Online (Sandbox Code Playgroud)