Since @hirolau's already taken swapcase
, I offered an alternative (even though I prefer his answer). Alas, @Stefan identified a flaw, but suggested a nice fix:
str = '1654AaBcDddeeFF'
order_array = [*'0'..'9',*'a'..'z',*'A'..'Z']
str.each_char.sort_by { |c| order_array.index(c) }.join
#=> "1456acdeABDF"
(I am a mere scribe.)
One advantage of this approach is that you could use it for other orderings. For example, if:
str = '16?54!AaBcDdde,eFF'
and you also wanted to group the characters `'!?,' at the beginning, in that order, you could write:
order_array = [*'!?,'.chars,*'0'..'9',*'a'..'z',*'A'..'Z']
str.each_char.sort_by { |c| order_array.index(c) }.join
#=> "!?,1456acdeABDF"
We can make this a bit more efficient by converting order_array
to a hash. For the last example:
order_hash = Hash[order_array.each_with_index.to_a]
then:
str.each_char.sort_by { |c| order_hash[c] }.join
# => "!?,1456acddeeABDFF"