Right now I have an array
letter = ['a','b','c','a','b','c','a','b','b']
Can someone kindly explain the following return value?
letter.sort! { |x| letter.count(x) }
#=> ["b", "b", "a", "c", "c", "a", "b", "b", "a"]
Right now I have an array
letter = ['a','b','c','a','b','c','a','b','b']
Can someone kindly explain the following return value?
letter.sort! { |x| letter.count(x) }
#=> ["b", "b", "a", "c", "c", "a", "b", "b", "a"]
When you define a sort
or sort!
block you are obligated to take in two arguments, typically a
and b
. These are the two elements the sort operation is comparing at the time, so this block will be called repeatedly with various pairs.
There are constraints imposed on what you return, that by definition you should return -1, 0 or +1 only. Other values may work, but are not part of the specification. You return -1
if a
should come after b
in the series, 0
if they are equivalent, and 1
if b
should come after a
.
Additionally for any given set of a
, b
and c
values, you should return consistent results such that if a < b
and b < c
then a < c
. If you return random values your array will be a total mess and won't necessarily be completely sorted. Optimizations in the sort algorithm depend on consistent results. If you say a
comes after c
then all values that come after a
must come after c
as well.
It's highly probable that Ruby is collapsing all positive values into an indication that the second term comes before the first. Since you return a positive value for all cases you're telling the sort algorithm that all values come before all other values, which is total nonsense, as that can never happen.
So, in short, you're getting junk back because you're giving the sort
function junk and the Garbage In, Garbage Out principle applies.
The way around this is to use the sort_by
method which takes only one argument and handles these comparisons for you:
letters.sort_by! { |x| letter.count(x) }