# Ruby’s Sort and Sort_by Whenever I hear the word sort in a programming context, I get instant flashbacks from my high-school days. It’s like going back in time for a few seconds.

I can’t seem to remember when and why I switched from “OMG” to “Oh! Cool!”. But anyway, back to sorting, and sorting algorithms.

Just a quick recap of a few sorting algorithms I’m sure you’ve heard of.

## Bubble sort

1. Start at the beginning of the list.
2. Compare each pair of elements in turn.
3. If you need to swap them (i.e. left is bigger than the right), you swap them.
4. You repeat the process until there are no more swaps.

One way to optimize bubble sort is to remove the last element from the list at each pass (because it’s the largest value).

## Merge sort

1. You split your list of elements smaller and smaller lists until you get to a list of pairs.
2. You sort each pair.
3. You merge the pairs in order.

Merge sort works better than bubble sort for larger lists.

## Quicksort

1. Choose a pivot.
2. Put all the numbers smaller than or equal to the pivot to its left.
3. Put all the numbers larger than the pivot to its right.
4. For each sublist, choose a pivot and repeat the process until there is just one or no elements in each list.

The way you choose the pivot can have a great impact on the operation’s performance. Ideally, you want to choose the pivot in the middle of the list.

## Working with the Ruby sort method

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. Let us see an example.

### Sorting an array in descending order with sort

Here’s how the `sort` method works when a block is passed to it.

`[1, 2, 3].sort { |a, b| b <=> a } # => [3, 2, 1]`

You can probably imagine how that [block]({% post_url 2015-01-20-mastering-ruby-blocks-in-less-than-5-minutes %}) could easily fit any custom sorting preference.

You can learn more about arrays and see a few more examples on how to sort them in [Learn How to Use Ruby Arrays in Less Than 10 Minutes]({% post_url 2018-07-03-learn-how-to-use-ruby-arrays %}).

## The Ruby sorting operator (`<=>`)

Also called the spaceship operator, takes two parameters and returns one of three values.

• `0` if the two parameters are equal.
• `-1` if the first parameter is less than the second parameter.
• `1` if the first parameter is greater than the second parameter.

Note that when the result is `0`, the order of the elements is unpredictable.

## Sort vs. sort_by

The difference between `sort` and `sort_by` is in the parameters to the block.

`sort` receives two objects that you have to compare using their `<=>` operator.

`sort_by` receives just one object, and you have to call a method that will be used to map over the collection. If that sounds confusing, you’re not alone. So let us see an example.

If you want to compare sort a two-dimensional array, by the size of each array in the list, you can call `:size` on the object the block receives.

```matrix = [
[1, 2, 3, 4, 5, 6],
[1, 2, 3],
[1, 2, 3, 4, 5],
[:a, :b, :c, :d]
]

matrix.sort_by { |obj| obj.size }
# => [
[1, 2, 3],
[:a, :b, :c, :d],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 6]
]```

You can also do multiple sorting, where you sort using multiple values. If for example you want to sort by first and last names, you can do this.

```Person = Struct.new(:fname, :lname)

p1 = Person.new("John", "Doe")
p2 = Person.new("Jane", "Doe")
p3 = Person.new("Marry", "Mackan")
p4 = Person.new("John", "Beck")

[p1, p2, p3, p4].sort_by { |p| [p.fname, p.lname] }
# => [
#<struct  fname="Jane", lname="Doe">,
#<struct  fname="John", lname="Beck">,
#<struct  fname="John", lname="Doe">,
#<struct  fname="Marry", lname="Mackan">
]```

Without a block, `sort_by` returns [an enumerator]({% post_url 2018-07-06-what-is-a-ruby-enumerable-and-why-would-you-use-it %}).

When you are dealing with larger collections, `sort_by` is usually what you want to use.

## How to sort a string’s characters alphabetically?

The `chars` method returns an array of characters. So you can just sort that array, and then join the elements back into a string.

`"jhmaeb".chars.sort.join # => "abehjm"`

And if you want to do a case insensitive sort, here’s how.

`"cdBghaZosa".chars.sort(&:casecmp).join # => "aaBcdghosZ"`

If you’re interested in learning more about how strings work in Ruby, check out How to Use Strings in Ruby.

## How to Sort a Hash in Ruby

Often you want to sort a `Hash` just like you sort an `Array`. A hash is a list of key/value pairs. And it also includes the Enumerable module.

So let us say you want to sort a hash by its keys.

```my_hash = {
name: "John",
age: 21,
email: "john@example.com"
}

my_hash.sort_by { |k, v| k }
# => [
[:age, 21],
[:email, "john@example.com"],
[:name, "John"]
]```

And if you want to sort it by value, it’s just as easy `my_hash.sort_by { |k, v| v }`.

As you can see, the result is not a `Hash`. It’s a two dimensional `Array`.

If you want to turn it into a hash, you can call `to_h` on it.

### How to sort an array of hashes in ruby

If you’ve done any Rails development, I’m sure you’ve come across this one.

```scores = [
{name: "Superman", score: 745},
{name: "Ironman", score: 9},
{name: "Batman", score: 10}
]

scores.sort_by { |h | h[:name] }
# => [
{:name=>"Batman", :score=>10},
{:name=>"Ironman", :score=>9},
{:name=>"Superman", :score=>745}
]```