Bug #12221
closedEnumerable#sort_by method doesn't work properly when the array has more than 6 elements and you pass nil to the block
Description
%w(1 2).sort_by { |i| nil }
# => ["1", "2"]
# ...
%w(1 2 3 4 5 6).sort_by { |i| nil }
# => ["1", "2", "3", "4", "5", "6"]
So far, so good...
But look what happens when you have 7 or more elements:
%w(1 2 3 4 5 6 7).sort_by { |i| nil }
# => ["4", "2", "3", "1", "5", "6", "7"]
%w(1 2 3 4 5 6 7 8).sort_by { |i| nil }
# => ["8", "2", "3", "4", "5", "6", "7", "1"]
%w(1 2 3 4 5 6 7 8 9).sort_by { |i| nil }
# => ["9", "2", "3", "4", "5", "6", "7", "8", "1"]
%w(1 2 3 4 5 6 7 8 9 10).sort_by { |i| nil }
# => ["10", "2", "3", "4", "5", "6", "7", "8", "9", "1"]
Updated by sawa (Tsuyoshi Sawada) over 8 years ago
What is wrong with it?
Updated by duerst (Martin Dürst) over 8 years ago
- Status changed from Open to Rejected
Tsuyoshi Sawada wrote:
What is wrong with it?
To expand on this, you tell Ruby that all the values in the array should be 'valued' at nil. Therefore, they are equal, and any order will be correct. You can exchange nil with any other constant, and get the same result. It looks somewhat surprising in your examples, but the reason that the values get shuffled around is that in general (i.e. when most values are not equal), it leads to an efficient algorithm.
To get what you want, juts use the original array :-). Ruby's sort methods are not stable (i.e., they don't keep the original order if two elements compare as equal). Just do a search for Ruby stable sorting, and you will find a lot of useful explanations.