Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array of strings in Ruby

Tags:

I have learned two array sorting methods in Ruby:

array = ["one", "two", "three"] array.sort.reverse! 

or:

array = ["one", "two", "three"] array.sort { |x,y| y<=>x } 

And I am not able to differentiate between the two. Which method is better and how exactly are they different in execution?

like image 359
poorvank Avatar asked May 19 '13 18:05

poorvank


People also ask

How can you sort an array Ruby?

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.

How do you sort a string by length in Ruby?

arr = arr. sort{|x,y| x. length - y. length} works too.

Can you sort elements in a Ruby hash object?

Sorting Hashes in RubyTo sort a hash in Ruby without using custom algorithms, we will use two sorting methods: the sort and sort_by. Using the built-in methods, we can sort the values in a hash by various parameters.


2 Answers

Both lines do the same (create a new array, which is reverse sorted). The main argument is about readability and performance. array.sort.reverse! is more readable than array.sort{|x,y| y<=>x} - I think we can agree here.

For the performance part, I created a quick benchmark script, which gives the following on my system (ruby 1.9.3p392 [x86_64-linux]):

                              user     system      total        real array.sort.reverse        1.330000   0.000000   1.330000 (  1.334667) array.sort.reverse!       1.200000   0.000000   1.200000 (  1.198232) array.sort!.reverse!      1.200000   0.000000   1.200000 (  1.199296) array.sort{|x,y| y<=>x}   5.220000   0.000000   5.220000 (  5.239487) 

Run times are pretty constant for multiple executions of the benchmark script.

array.sort.reverse (with or without !) is way faster than array.sort{|x,y| y<=>x}. Thus, I recommend that.


Here is the script as a Reference:

#!/usr/bin/env ruby require 'benchmark'  Benchmark.bm do|b|   master = (1..1_000_000).map(&:to_s).shuffle   a = master.dup   b.report("array.sort.reverse      ") do     a.sort.reverse   end    a = master.dup   b.report("array.sort.reverse!     ") do     a.sort.reverse!   end    a = master.dup   b.report("array.sort!.reverse!    ") do     a.sort!.reverse!   end    a = master.dup   b.report("array.sort{|x,y| y<=>x} ") do     a.sort{|x,y| y<=>x}   end end 
like image 59
tessi Avatar answered Dec 21 '22 19:12

tessi


There really is no difference here. Both methods return a new array.

For the purposes of this example, simpler is better. I would recommend array.sort.reverse because it is much more readable than the alternative. Passing blocks to methods like sort should be saved for arrays of more complex data structures and user-defined classes.

Edit: While destructive methods (anything ending in a !) are good for performance games, it was pointed out that they aren't required to return an updated array, or anything at all for that matter. It is important to keep this in mind because array.sort.reverse! could very likely return nil. If you wish to use a destructive method on a newly generated array, you should prefer calling .reverse! on a separate line instead of having a one-liner.

Example:

array = array.sort array.reverse! 

should be preferred to

array = array.sort.reverse! 
like image 37
James Brewer Avatar answered Dec 21 '22 20:12

James Brewer