7

What's the best way to sort an Enumerable in descending order?

I've been doing @array.sort.reverse or @array.sort_by{|song| song.title }.reverse

I suppose I could do something like @array.sort{|a, b| b.title <=> a.title}, but I find this hard to read and verbose.

Translunar
  • 3,739
  • 33
  • 55
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272

2 Answers2

5

The performance of Array.reverse is not very bad. What costs you by using @array.sort.reverse is an extra array duplication plus the reverse (n/2 element switches). So yes, I think that should be acceptable if you think it's read clearer.

See its source for details. And also, I think using @array.sort.reverse does provide 'slightly' better readability (but it's not very hard to read any way).

bryantsai
  • 3,405
  • 1
  • 30
  • 30
  • 1
    sort.reverse is not much slower than sort, and it's way faster than anything fancy. I benchmarked array.sort, array.sort.reverse, and array.reverse_sort (my monkey-patch solution, which I've since deleted as "an obvious piece of junk") on 1,000,000 random floats and got times of 2.4, 2.5 and 24.8 seconds, respectively. – Wayne Conrad Jan 27 '10 at 00:05
3

I'm not sure whether this works any better than Wayne Conrad's self-described "obvious piece of junk," but you could define Enumerable#sort_by_descending as

Enumerable.class_eval do
  def sort_by_descending(&block)
    sort { |a, b| block.bind(b).call <=> block.bind(a).call }
  end
end

Then call it as follows:

@songs.sort_by_descending(&:title)
Community
  • 1
  • 1
James A. Rosen
  • 64,193
  • 61
  • 179
  • 261