1

I really don't understand the following sorting method:

books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]

books.sort! { |firstBook, secondBook| firstBook <=> secondBook }

How does the this work? In the ruby books, they had one parameter for example |x| represent each of the values in the array. If there is more than one parameter (firstBook and secondBook in this example) what does it represent??

Thank you!

4 Answers 4

4

The <=> operator returns the result of a comparison.

So "a" <=> "b" returns -1, "b" <=> "a" returns 1, and "a" <=> "a" returns 0.

That's how sort is able to determine the order of elements.

Sign up to request clarification or add additional context in comments.

Comments

1

Array#sort (and sort!) called without a block will do comparisons with <=>, so the block is redundant. These all accomplish the same thing:

books.sort!
books.sort_by!{|x| x}
books.sort!{|firstBook, secondBook| firstBook <=> secondBook}

Since you are not overriding the default behavior, the second and third forms are needlessly complicated.

So how does this all work?

The first form sorts the array by using some sorting algorithm -- it's not relevant which one -- which needs to be able to compare two elements to decide which comes first. (More on this below.) It automatically, behind the scenes, follows the same logic as the third line above.

The middle form lets you choose what to sort on. For example: instead of, for each item, just sorting on that item (which is the default), you can sort on that item's length:

books.sort_by!{|title| title.length}

Then books is sorted from shortest title to longest title. If all you are doing is calling a method on each item, there's another shortcut available. This does the same thing:

books.sort_by!(&:length)

In the final form, you have control over the comparison itself. For example, you could sort backwards:

books.sort!{|first, second| second <=> first}

Why does sort need two items passed into the block, and what do they represent?

Array#sort (and sort!) with a block is how you override the comparison step of sorting. Comparison has to happen at some point during a sort in order to figure out what order to put things in. You don't need to override the comparison in most cases, but if you do, this is the form that allows that, so it needs two items passed into the block: the two items that need to be compared right now. Let's look at an example in action:

[4, 3, 2, 1].sort{|x, y| puts "#{x}, #{y}"; x <=> y}

This outputs:

4, 2
2, 1
3, 2
3, 4

This shows us that in this case, sort compared 4 and 2, then 2 and 1, then 3 and 2, and then finally 3 and 4, in order to sort the array. The precise details are irrelevant to this discussion and depend on the sorting algorithm being used, but again, all sorting algorithms need to be able to compare items in order to sort.

3 Comments

in books.sort_by!{|x| x} syntax, what I dont understand is: x is the thing to be sorted, so why it isn't books.sort_by!(x){}?? Also, with the correct ruby syntax, I wouldnt even know how to pass the arugement x back to sort_by!() method
Actually, books is the thing to be sorted, and x is consecutively set to each item in books. It's not useful if all you do is return x from the block, but it is useful if you want to sort on something other than the item itself (e.g., the length of the item -- see again the So how does this all work? section of my answer).
Now that (after 1 day) I understand blocks/yield better, I can see that my question didn't make that much sense.
0

The block given inside {} is passed as a comparing function for method sort. |a, b| tells us that this comparing function takes 2 parameters (which is expected number of arguments since we need to compare).

This block is executed for each element in array but if we need one more argument we take next element after this.

Comments

0

See http://ruby-doc.org/core-2.0/Array.html#method-i-sort for an explanation. As for a single-parameter method referred to in your books, I can only guess you were looking at sort_by. Can you give an example?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.