Input string:
1654AaBcDddeeFF
Output string:
1456acddeeABDFF
Code I tried:
test_array = []
'1654AaBcDddeeFF'.each_byte do |char|
test_array << char
end
test_array.sort.pack('C*')
# => 1456ABDFFacddee
But I would like to see the upper case characters at last.
In Ruby, it is easy to sort an array with the sort() function. When called on an array, the sort() function returns a new array that is the sorted version of the original one.
The question becomes: how can you sort an array in reverse order, or sort strings in a case-insensitive manner? Ruby lets you do this by specifying how comparison ought to be done. You put this in a do / end block after the word sort . The following code will sort an array in descending order.
The Ruby sort method works by comparing elements of a collection using their <=> operator (more about that in a second), using the quicksort algorithm. You can also pass it an optional block if you want to do some custom sorting. The block receives two parameters for you to specify how they should be compared.
You can use the sort method on an array, hash, or another Enumerable object & you'll get the default sorting behavior (sort based on <=> operator) You can use sort with a block, and two block arguments, to define how one object is different than another (block should return 1, 0, or -1)
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"
What about this?
p '1654AaBcDddeeFF'.each_char.sort_by(&:swapcase).join #=> "1456acddeeABDFF"
Edit: As @Cary Swoveland pointed out .chars
is just a shortcut for .each_char.to_a
and since we do not need to to_a
here .each_char
is a better method to use
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With