1

我真的不明白下面的排序方法:

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 }

这是如何工作的?在红宝石书籍中,它们有一个参数,例如|x|代表数组中的每个值。如果有多个参数(本例中为 firstBook 和 secondBook),它代表什么?

谢谢!

4

4 回答 4

4

<=>运算符返回比较结果。

所以"a" <=> "b"返回 -1,"b" <=> "a"返回 1,然后"a" <=> "a"返回 0。

这就是如何sort能够确定元素的顺序。

于 2013-06-16T18:00:22.690 回答
1

不带块调用的Array#sort (and sort!) 将与 进行比较<=>,因此该块是多余的。这些都完成了同样的事情:

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

由于您没有覆盖默认行为,因此第二种和第三种形式不必要地复杂。

那么这一切是如何运作的呢?

第一种形式通过使用某种排序算法对数组进行排序——哪个不相关——它需要能够比较两个元素来决定哪个先出现。(下面有更多内容。)它在幕后自动遵循与上面第三行相同的逻辑。

中间的表格让您选择要排序的内容。例如:您可以对每个项目的长度进行排序,而不是对每个项目进行排序(这是默认设置):

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

然后books从最短的标题到最长的标题排序。如果您所做的只是在每个项目上调用一个方法,那么还有另一个可用的快捷方式。这做同样的事情:

books.sort_by!(&:length)

在最终形式中,您可以控制比较本身。例如,您可以向后排序:

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

为什么sort需要将两个项目传递到块中,它们代表什么?

Array#sort(and sort!) with a block 是您如何覆盖排序的比较步骤。比较必须在排序过程中的某个时刻进行,以便确定将事物放入的顺序。在大多数情况下,您不需要覆盖比较,但如果您这样做,这是允许这样做的形式,所以它需要将两个项目传递到块中:现在需要比较的两个项目。让我们看一个实际的例子:

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

这输出:

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

这向我们表明,在这种情况下,sort比较4and 2, then 2and 1, then 3and 2,然后 finally 3and 4,以便对数组进行排序。确切的细节与此讨论无关,取决于所使用的排序算法,但同样,所有排序算法都需要能够比较项目才能进行排序。

于 2013-06-16T19:01:07.617 回答
0

{} 中给出的块作为方法排序的比较函数传递。|a,b| 告诉我们这个比较函数有 2 个参数(这是我们需要比较的预期参数数量)。

这个块是针对数组中的每个元素执行的,但是如果我们需要更多参数,我们将在此之后获取下一个元素。

于 2013-06-16T18:09:13.880 回答
0

有关说明,请参见http://ruby-doc.org/core-2.0/Array.html#method-i-sort。至于您书中提到的单参数方法,我只能猜测您正在查看 sort_by。能给我举个例子吗?

于 2013-06-16T18:11:45.097 回答