19 - how does <=> actually work?


#1

Hi there,
Basically I just want to figure out how the <=> actually does the sorting? What is the process? does is it take each variable in turn and compare it to the others? Basically my question is, how do the fruit come to find themselves in alphabetical order? I think using the variable names "firstFruit, secondFruit" might be confusing me...


#2

@supasuma,
Could you give an example code....so to better understand the question...


#3

<=> can return four values: 1, 0, -1, or nil. If the two values are equivalent, it returns 0. If the value on the left is great than the value on the left, then it returns 1. If the value on the right is greater than the value on the left, it returns -1. As for when it returns nil, I think it's caused when the two values don't can't be compared.


#4

@supasuma, @tehluigi,
Maybe....
http://stackoverflow.com/questions/827649/what-is-the-ruby-spaceship-operator


#5

but how to claculate this values??????


#6

I'm also confused by this. The code example is this:

fruits = ["orange", "apple", "banana", "pear", "grapes"]

fruits.sort! do |firstFruits, secondFruits|
secondFruits <=> firstFruits
end

However, this makes no sense to me...is firstFruits a variable? Is 'first' a keyword in Ruby? If so then it makes more sense, but it's not explained well in the content.

For me, it's far, far, far easier to simply do:

fruits.sort!
fruits.reverse!

However the console won't allow it on a latter example.


#7

@courseplayer23243,
From
http://docs.ruby-lang.org/en/2.0.0/Array.html

sort! → ary click to toggle source

sort! { |a, b| block } → ary

Sorts self in place.

Comparisons for the sort will be done using the <=> operator or using an optional code block.

The block must implement a comparison between a and b, and return -1, when a follows b, 0 when a and b are equivalent, or +1 if b follows a.

See also Enumerable#sort_by.
a = [ "d", "a", "e", "c", "b" ]
a.sort! #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]

( a do ... end can also be expressed by { .... } )


#8

firstFruits and secondFruits are only parameters that you provide to the method .sort! The same happen with .each and many other methods. I used letters like this:

fruits = ["orange", "apple", "banana", "pear", "grapes"]
fruits.sort! do | i, x |
x <=> i
end

and works just fine. They are not variables per se, their just parameters that are used to looped through the objects in the array. In your case, Ruby looks at your code and analyze the iteration(loop) of the firstFruits through all elements in the array, and put the second parameter working by comparison, in your case secondFruits. "first" and "second" are not keywords, in this case, that ruby assume to make the comparison. As you can see in my code, you can name them what you want.

And how does the comparison actually happen:

the comparison operator <=> works both way, ascending and descending, following the order that your define in your block. Then, the comparison is made by comparing, in your case, firstFruit and secondFruit, until he gets the result. If your consider the letter "A" as having the number 1, and "B" the number 2, and so on (which actually happen, because Ruby makes a binary representation of each character of each element (string in this case)), you easily see that one fruit is higher than other. So descending the order, the higher strings come first, in this case pear.

Hope this helped.


#9

@tagpro75974 @courseplayer23243 @leonhard.wettengmx.n

I gotta resurrect this because I'm still not buying it ( :stuck_out_tongue:)
So you have this:

fruits = ["orange", "apple", "banana", "pear", "grapes"]
fruits.sort! do | i, x |
x <=> i
end

Step by step, what happens? What I see is this:

1) apple <=> orange will return -1 (a is less than o)

why doesn't the -1 move apple further towards the 'beginning' [0] of the array? We want apple at the end of the array (descending order)

2) banana <=> apple will return 1 (b is greater than a)

Same logic - why does this move banana further to the beginning instead of the end?

3) pear <=> banana will return 1
4) grapes <=> pear will return -1

At this point, it seems like the loop would be done - but I don't see where the order comes from. All that it returned was 1's and -1's. Does it reiterate through until all the arguments return 1 (ie, the array is sorted)?


#10

I agree, this is not straightforward and needs more explanation.

Dear Codecademy moderators, could you please explain in some more detail what the sort method is actually doing?


#11

@stickysplatt
@pyrockstar60369
Maybe reading
== discussion / opinions ==
http://stackoverflow.com/questions/827649/what-is-the-ruby-spaceship-operator
== the Book ==
http://ruby-doc.org/core-2.3.1/Comparable.html


Why put 2 elements
#12

I didn't find those particularly useful, and I agree - this is very confusing. I came across this youtube video on merge sort which really cleared things up for me. Maybe it will help you, too.


#13

I agree - @leonhard.wettengmx.n, those sites merely explain the spaceship operator (which I understand), not the way the sort function uses it.

@kirapilot, that video is helpful! I suppose the sort function works through a similar type of logic, continuing to sort until the whole thing is sorted. I suppose I can let my mind rest on it for now - but I would still love to see a step by step explanation of what exactly it is doing (a la my earlier post, but completed)
p.s. that dude's voice reminds me of something i can't quite put my finger on. love the dreamy atmosphere music Lol


#14

In the above, the compare order is the reverse of the block parameters order, so the sort order is reversed (highest to lowest => descending).

When x compare i returns -1, x moves to the other side of i (the right side). This process is repeated until no more swaps can be performed. The mechanics are explained in the merge sort method (though I haven't watched the video).


#15

@pyrockstar60369

This link the 2nd article
http://stackoverflow.com/questions/26581619/rubys-operator-and-sort-method?lq=1

To make sure you understand the Ruby syntax:

foo = [4, 5, 6]
puts foo.sort {|a,b| a <=> b}

The block of code (surrounded by {}'s) is what Ruby would do any way when it sorts from lowest to highest.
But suffice it to say that the first iteration of the .sort method
will assign the variables between the pipes (a, b) the first two elements of the array.
So for the first iteration a=4 and b=5, and since 4<5, that results in a -1, which Ruby takes it to mean to NOT swap the array.
It does this for a second iteration,
meaning a=5 and b=6, sees that 5<6, results in -1 and leaves the array alone.
Since all the <=> results were -1, Ruby stops looping through and feels the array is sorted at [4,5,6].
Otherwise the array will be iterated once more !!!!

test=["d","a","g","b"]
sorted_test_desc = test.sort { |down,up| up<=>down }
sorted_test_asc = test.sort { |down,up| down<=>up }
puts sorted_test_desc
puts "==="
puts sorted_test_asc

puts "==destroyed=="
test=["d","a",nil,"b"]
sorted_test_desc = test.sort { |down,up| up<=>down }

#16

@pyrockstar60369 Glad it was helpful! Yeah, I hate not knowing things all the way through, but I think the bottom line is that sorting is pretty involved, and we should learn the basics right now and tackle the algorithms behind the basics later. :slight_smile:

Just FYI, guys, the video I posted for merge sort was helpful for my understanding, but Ruby's sort algorithm is actually something called quicksort. It's very similar to merge sort and also complex, relying on a series of randomized pivots. You can find videos on YouTube, but I'd leave well enough alone if you're just learning Ruby, like I am.

Best of luck!
Kira


#17

@kirapilot @leonhard.wettengmx.n @mtf Thanks guys! Great answers, I feel like one of my toes touched the bottom. Best of times to tall!


#18

Actually I think it's bubble sort.