Feature #8422

add Enumerable#reverse_sort and Enumerable#reverse_sort_by

Added by Hans Mackowiak 11 months ago. Updated 10 months ago.

[ruby-core:55046]
Status:Feedback
Priority:Normal
Assignee:-
Category:-
Target version:-

Description

they are better when you want descending order,
enum.sort.reverse
does work too, but it is to slow because it needs to build that result array twice

they both can be defined just like #sort and #sort_by but negates the result of the compare block

History

#1 Updated by Yukihiro Matsumoto 11 months ago

  • Status changed from Open to Feedback

It can be done by a.sort{|a,b| b<=>a}. Do we really need to define new methods?

Matz.

#2 Updated by Marc-Andre Lafortune 11 months ago

matz (Yukihiro Matsumoto) wrote:

It can be done by a.sort{|a,b| b<=>a}.

That will typically be much slower though.

Currently, the best way to do a reverse sort, performance-wise, is a.sort.reverse!

For a random 100 number array, for example:

sort.reverse! is faster than sort.reverse by 10% ± 1.0%
sort.reverse is faster than sortby by 6x ± 0.1
sort
by is faster than sort by 60% ± 1.0%

Code: https://gist.github.com/marcandre/5604592

#3 Updated by Boris Stitnicky 11 months ago

-1, feature creep
But I'm for defining reverse! as O(1), not really reversing anything, just treating the last element as first and first as last. (I do not know how collections are exactly implemented, so I am not sure whether this is possible.)

#4 Updated by Eric Hodel 10 months ago

=begin
How do you sort an infinite Enumerable?

ruby -rprime -e 'p Prime.each.reverse_sort.take 10'
=end

#5 Updated by Marc-Andre Lafortune 10 months ago

drbrain (Eric Hodel) wrote:

How do you sort an infinite Enumerable?
ruby -rprime -e 'p Prime.each.reverse_sort.take 10

I'm not sure what your point is. How is that different from p Prime.each.sort.take 10? Moreover, an alternative request could be to add Array#reversesort{by}.

Maybe we should consider a variation on sort that allows multiple criteria and independent sort directions?

#6 Updated by Eric Hodel 10 months ago

=begin
Neither (({Prime.each.reverse_sort.take 10})) nor (({Prime.each.sort.take 10})) will return as there is no last value for infinite streams. You can neither reverse nor sort an infinite stream.

I believe adding the feature to Enumerable doesn't fit with its existing functionality (all beginning-of-stream oriented).

We need feedback from the submitter. Without it this issue should be closed.
=end

#7 Updated by Marc-Andre Lafortune 10 months ago

drbrain (Eric Hodel) wrote:

Neither (({Prime.each.reverse_sort.take 10})) nor (({Prime.each.sort.take 10})) will return as there is no last value for infinite streams.

Of course. But you are aware that Enumerable has a sort method that acts as a shortcut to to_a.sort?

We need feedback from the submitter. Without it this issue should be closed.

The relevant question here is "should there be a dedicated way to do a reverse sort". The question of where that method should be (Array or Enumerable) is accessory.

#8 Updated by Hans Mackowiak 10 months ago

my idea would be this, for ruby it may be cood if its converted into C++ code

module Enumerable
def reverse_sort(&block)
block ||= proc {|x,y| x <=> y }
sort {|x,y| - block.call(x,y)}
end

def reversesortby
return toenum(method) unless blockgiven?
sort_by{|x| - yield(x)}
end
end

Also available in: Atom PDF