Ruby排序功能究竟做了什么?

时间:2014-08-22 17:12:02

标签: ruby arrays sorting

让我先说一下我是Ruby的新手(非常明显)。我在Codecademy上学习Ruby,并且我对sort函数感到困惑。以用作为例:

list = [3,2,1,4]
list.sort { |a,b| b <=> a }

我知道这将按降序返回数组 - [4,3,2,1]。我完全不明白为什么。我知道当调用sort函数时,数组中的数字会被传递到函数中并进行比较,然后返回-1,0或1 - 但是接着是什么?例如,我猜这是首先要比较的东西:

[3 <=> 2] = 1

但它对返回的1做了什么?在获得1后,数组会是什么样子?

我很困惑,因为我不明白如何逆转比较(a&lt; =&gt; b&b =&lt; a&gt; a)会改变数组的排序方向。除非我弄错了,否则不会&#34; 1&lt; =&gt; 2&#34;基本上返回&#34; 1来自2&#34;,而&#34; 2&lt; =&gt; 1&#34;返回&#34; 2来自1&#34;?这或多或少是相同的,但结果明显不同。

3 个答案:

答案 0 :(得分:5)

“宇宙飞船”操作员<=>不会返回“a a before b”之类的英语。它返回sort需要知道的内容:两个元素相互关联的位置。具体来说,它返回您提到的-1,0或1值。

a <=> b中,如果a小于b(通过对a为实例的类使用的比较方法),则返回 - 1。如果它们相等,则返回0;如果a大于b,则返回值为1.

执行b <=> a时,返回的值基于b而非a,因此如果a较小,则会得到1,而在执行时得到-1 a <=> b

因此,虽然英语含义相同,但魔鬼在细节中:-1,0或1返回值。该值精确地告诉Ruby两个元素如何适合排序数组。

这三个数字的神奇之处在于Ruby使用的quicksort algorithm。尝试精确解释该算法的工作方式超出了范围,但您基本上可以将其视为对许多值的简单比较。对于数组中的每个项目,使用数组中的另一个项目调用<=>,以确定两个项目相对于彼此的位置。一旦进行了足够的比较,所有这些单独项目的位置都是已知的,并且已完成排序。

作为一个简单的(并非技术上准确,但足够接近)示例,请考虑数组[3, 2, 7, 1]。您可以获取一个值来比较其他值,以便开始排序。我们将选择3.运行3与所有其他数字的比较给我们:

  • 3 <=> 2 == 1:3大于2,因此2必须位于3的左侧。我们的数组现在可能如下所示:[2, 3, 7, 1]
  • 3 <=> 7 == -1:3小于7,因此7必须是3的右边。我们的数组继续看起来像之前一样,因为7已经在右边。
  • 3 <=> 1 == 1:3大于1,因此1必须位于3的左侧。我们的数组现在看起来像这样:[2, 1, 3, 7]

我们知道7必须是正确的,因为它是“大于3”侧的唯一元素。所以我们只需要弄清楚3:1和2之前所有内容的排序顺序。运行类似的比较,我们显然将1和2交换为[1, 2, 3, 7]

我希望这有帮助!

答案 1 :(得分:1)

比较得到两个参数,如果第一个参数小于第二个参数则返回-1,如果两个参数相等则返回0,如果第二个参数更大则返回1比第一个论点。交换两者时,它会反转结果。 <=>并不关心其操作数的来源,因此虽然更改不会添加有关ab之间关系的任何额外信息,但它会反转<=>(1 <=> 2) == -1 (2 <=> 1) == 1 之间的关系{1}},它反转了排序顺序。

1 <=> 2

作为排序功能,您不会获得2 <=> 1-1;得到1或{{1}}。从任何一个数字开始,您决定传递给比较的参数应该在结果的后面。

答案 2 :(得分:0)

  

除非我弄错了,否则不会&#34; 1&lt; =&gt; 2&#34;基本上返回&#34; 1来自2&#34;,而&#34; 2&lt; =&gt; 1&#34;返回&#34; 2来自1&#34;?这或多或少是相同的,但结果明显不同。

不,是的。问块的问题是:&#34;左边的元素是在右边之前还是之后?&#34;通过左右交换,您可以交换订单。

所以,答案是:你本身并没有扭转比较,但是你正在颠倒sort方法的想法,哪个是剩下的,哪个是正确的。

块的返回值由sort解释为:

  • 0:订单无关紧要
  • 1:元素已按正确顺序排列
  • -1:元素的顺序错误

通过左右交换,您可以交换块是否告诉sort元素的顺序是正确还是错误。

请注意,Quicksort在这里完全不相关。重要的是比较器块的合同。然后Quicksort,Shellsort,Insertion Sort,Bubblesort,Bogosort,Timsort或其他基于比较的排序是否使用该块并不重要。