Ruby自定义字符串排序

App*_*unu 5 ruby sorting string

输入字符串:

1654AaBcDddeeFF 
Run Code Online (Sandbox Code Playgroud)

输出字符串:

1456acddeeABDFF
Run Code Online (Sandbox Code Playgroud)

我试过的代码:

test_array = []
'1654AaBcDddeeFF'.each_byte do |char|
  test_array << char
end

test_array.sort.pack('C*')
# => 1456ABDFFacddee
Run Code Online (Sandbox Code Playgroud)

但我想最后看到大写字符.

hir*_*lau 13

那这个呢?

p '1654AaBcDddeeFF'.each_char.sort_by(&:swapcase).join #=> "1456acddeeABDFF"
Run Code Online (Sandbox Code Playgroud)

编辑:正如@Cary Swoveland指出.chars的只是一个捷径.each_char.to_a,因为我们不需要to_a这里.each_char是一个更好的方法使用

  • 好一个.也许是`each_char`而不是`chars`来避免创建临时数组. (2认同)

Car*_*and 5

由于@hirolau 已经被采用swapcase,我提供了一个替代方案(尽管我更喜欢他的答案)。唉,@Stefan 发现了一个缺陷,但提出了一个很好的修复方法:

str = '1654AaBcDddeeFF'

order_array = [*'0'..'9',*'a'..'z',*'A'..'Z']
str.each_char.sort_by { |c| order_array.index(c) }.join
  #=> "1456acdeABDF" 
Run Code Online (Sandbox Code Playgroud)

(我只是一个抄写员。)

这种方法的一个优点是您可以将其用于其他订购。例如,如果:

str = '16?54!AaBcDdde,eFF'
Run Code Online (Sandbox Code Playgroud)

并且您还想将字符“!?”放在开头,按照该顺序,您可以编写:

order_array = [*'!?,'.chars,*'0'..'9',*'a'..'z',*'A'..'Z']
str.each_char.sort_by { |c| order_array.index(c) }.join
  #=> "!?,1456acdeABDF" 
Run Code Online (Sandbox Code Playgroud)

order_array我们可以通过转换为哈希来提高效率。对于最后一个例子:

order_hash = Hash[order_array.each_with_index.to_a]
Run Code Online (Sandbox Code Playgroud)

然后:

str.each_char.sort_by { |c| order_hash[c] }.join
  # => "!?,1456acddeeABDFF"
Run Code Online (Sandbox Code Playgroud)