books = ["Charlie and the Chocolate Factory", "War and Peace", "Utopia", "A Brief History of Time", "A Wrinkle in Time"]
# To sort our books in ascending order, in-place
books.sort! { |firstBook, secondBook| firstBook <=> secondBook }
# Sort your books in descending order, in-place below
books.sort! do |first,second| first
first <=> second
end
books.reverse!
I’ve learned sorting method and I understand variables and what not. But I don’t understand why |first,second| and first exist. Can that whole line be explained? Obviously first and second are local variables (to the method) but those are defined in ||. Why is that second “first” there? How does this sort one by one? Most thorough explanation possible please.
So let me get this straight. When sorting you 100% always need TWO sorting variables (assumption made here that you always need 2)
The |first,second| are our variables that we will be sorting in the <=> operator (returns -1, 0 ,1 depdending on which one should be sorted first (-1 for “first”, 0 if they are the same, and 1 if “second” should be sorted first)
The |first, second| first tells the program that if first SHOULD be sorted first, then put first first? If the bolded there was “second” then it would tell the program "if first should be sorted over second, put second first (weird but logically that would work right?)
Hmm no that can’t be right. I changed the second and first around (the one after | |) and codecademy exercise returned the same result. I’m confused. Explanation please.
Hold up HOLD UP HOLD UP. I remove that second “first” instance AND THE PROGRAM STILL RUNS? What is this sorcery. Why do I even NEED that then? DO I?
Second question - I have the sort method…why do I also need <=> in there?
sort_by takes an array or a Hash (whatever) and sorts based on number or string or whatever. I get that.
Does sort ALWAYS have instance of <=> since that’s what the sort method relies on to sort crap? Just want to know if the sort univnersally will use <=>
Edit-I feel like that second instance after | | was poor reading from their example program. Weird it still let me work with it. I fully understand sort now except for my above question in the above paragraph.
That first hanging off the first line shouldn’t be there.
To help you understand it this is the equivalent javascript code
books.sort!(function(first, second) {
return first < second
});
The parameters between the pipes are the arguments to the block or function.
Blocks can either be between do and end or curlies { }
You don’t need any of this for sorting strings / numbers. Without a block they’ll sort alphabetically and numerically. You only need to provide a block if you’re sorting more complicated objects where you want to compare specific properties.
books.sort!
In those cases you always need two parameters to compare each item against.
<=> is a the Combined comparison operator. Returns 0 if first operand equals second, 1
if first operand is greater than the second and -1 if first operand is
less than the second.
Understood. sort! will take care of simple stuff. sort with the inner code will be for more complex.
sort_by ismore for arrays and Hashes?
Will more complex objects always need to be compared with <=>? Is that the only way? Or should I wait for possible later comparisons in a later tutorial?
Edit-Yes I understand the -1,0,1 part. Just curious about how universal it’s used in sort for objects/complex things.
I meant more along the lines of, is that the ONLY way to sort other complex objects? Are there others? Or if I will be sorting more complex objects, <=> is a one stop shop.
That’s a lot to look at. So it can compare sorts that we compare with compare. But basically <=> is the one stop shop. Thanks @markbrown4, I understand. Not sure why that second “first” was in my original code and codecademy allowed it to run. I got it working and went back over WHY it worked and I couldn’t for the life of me figure out why the sorting worked. Turns out it just had an extra word. Codecademy isn’t perfect I guess. Thank you!
Real quick - I learned that as of Ruby 1.9, doing Hashes (with symbols) in the form of
:symbol_here => “value” is no longer supported. Should I universally bedoing the below (and retain the previous information when reading other peoples outdated code?)