问题描述:

I recently came across a piece of code that used

array.sort{|x,y| y <=> x}

to sort an array of integers in descending order. I looked up the <=> operator and understand that it returns three different values, -1, 0, or 1, depending on whether or not one value is less than, greater to, or equal to the other other value.

But I cannot reason out why this would make the above code sort the array in descending order, but know that it definitely does thanks to IRB. What's going on here? Can somebody explain this to me?

网友答案:

For the same reasons that this:

array.sort{|x,y| x <=> y}

Sorts by ascending order.


Take this program for example:

[1,5,2,4,3].sort do |x,y|
  puts "---"
  puts x
  puts y
  puts x <=> y
  x <=> y
end

It'll output the two numbers that it's comparing, and then the result of the <=> during the sort. It outputs this:

---
1
2
-1 # 1 is less than 2
---
2
3
-1 # 2 is less than 3
---
5
2
1 # 5 is greater than 1
---
4
2
1 # 4 is greater than 2
---
5
4
1 # 5 is greater than 4
---
4
3
1 # 4 is greater than 3

If you reverse the order of x <=> y to be y <=> x, you're going to get the opposite result.

网友答案:

Because you did y <=> x, not x <=> y. Order of arguments is important.

网友答案:

I've chosen to give an answer that I hope will be understandable to most Ruby newbies.

Array#sort compares each pair of elements in the array. For each pair of elements x,y, sort's block returns -1 if x precedes y in the sort, 1 if y precedes x and 0 if either can precede the other. If no block is given, sort employs the block:

{ |x,y| x <=> y }

If, for example, x and y are strings, the method String#<=> might be defined like this:

class String
  def <=>(other)
    case
    when self < other then -1
    when self > other then  1
    else 0
    end
  end
end

Similarly, Array#<=> is invoked if x and y are arrays, and so on. For Fixnums, Bignums and Floats (all of which are from classes that descend from Numeric), the method Numeric#<=> is used, so that the array being sorted can contain a mix of those three data types.

If sort's block is:

{ |x,y| y <=> x }

the block returns the values shown here (with the values for the default x <=> y shown for comparison):

Now suppose we wish to sort the array [2,3,1,2]. For the default sort, the sort block with x <=> y returns the values shown here:

which causes sort to return [1,2,2,3]. If the sort block is

{ |x,y| y <=> x }

the sort block returns these values:

causing sort to return [3,2,2,1].

相关阅读:
Top