【问题标题】:Ruby Array#sort how it knows that the block should sort in ascending or descending orderRuby Array#sort 它如何知道块应该按升序或降序排序
【发布时间】:2022-01-20 12:27:01
【问题描述】:

https://stackoverflow.com/a/11427868/936494 已经有一个相关问题,但我想了解的是

使用时

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

它如何知道这个块应该按升序排序并且在使用时类似

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

它怎么知道这个块应该按降序排序?我很困惑,因为这两个块都使用了 spaceship 运算符,并且在 a.sort { |x, y| x &lt;=&gt; y } 的情况下,预计在每次比较期间都会返回以下内容@

  • -1 如果 x
  • 0 如果 x == y
  • 1 如果 x > y

a.sort { |x, y| y &lt;=&gt; x }的情况下进行每次比较

  • -1 如果 y
  • 0 如果 y == x
  • 1 如果 y > x

现在让我们举个例子:

2.3.2 :023 > a = [ "d", "a", "e", "c", "b" ]
 => ["d", "a", "e", "c", "b"]

当我们使用a.sort { |e1, e2| p [e1, e2]; e1 &lt;=&gt; e2 } 对其进行排序时,结果如下:

["d", "a"] (cmp result: 1)
["c", "b"] (cmp result: 1)
["e", "b"] (cmp result: 1)
["e", "c"] (cmp result: 1)
["a", "b"] (cmp result: -1)
["d", "b"] (cmp result: 1)
["d", "c"] (cmp result: 1)
["d", "e"] (cmp result: -1)
 => ["a", "b", "c", "d", "e"]

现在在这种情况下,它是如何知道将“a”放在第一位,然后是“b”,然后是“c”等等?

类似地,当我们使用a.sort { |e1, e2| p [e2, e1]; e2 &lt;=&gt; e1 } 对其进行排序时,结果如下:

["a", "d"] (cmp result: -1)
["b", "c"] (cmp result: -1)
["c", "e"] (cmp result: -1)
["e", "d"] (cmp result: 1)
["c", "d"] (cmp result: -1)
["c", "a"] (cmp result: 1)
["b", "a"] (cmp result: 1)
 => ["e", "d", "c", "b", "a"]

那么在这种情况下,它是如何知道将“e”放在第一位,然后是“d”,然后是“c”等等?并且考虑到两个元素的比较这一事实在这两个块中应该返回 1、0 还是 -1?

【问题讨论】:

  • 您的比较误导了您。您必须将x&lt;=&gt;y 中的第一个项目符号点与y&lt;=&gt;x 中的最后一个项目符号点进行比较,反之亦然:x &lt; y 等同于y &gt; xx &gt; y 等同于y &lt; x

标签: ruby sorting


【解决方案1】:

块返回的值告诉sort 哪个元素在列表中排在第一位。如果块返回1,则意味着第一个块参数将被视为“大于”第二个块参数,因此在排序结果中第一个块参数必须位于第二个之后。

一个有趣的事情是 Ruby 的 sort 算法利用了比较的传递性:在您的第一个示例中,它从未直接比较“a”和“c”,但其他比较表明“a”

表达式y &lt;=&gt; x 等价于-(x &lt;=&gt; y)(假设两个对象的类都实现了合理的宇宙飞船运算符)。因此,如果您按y &lt;=&gt; x 排序,则所有单独的比较都会被反转,并且排序后的数组必须以相反的顺序排列。

【讨论】:

  • “所有单独的比较都被反转,排序后的数组必须是相反的顺序”——这里的微妙之处很重要:它保证是相反的顺序,但不能保证是反向
【解决方案2】:

使用时

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

它如何知道该块应该按升序顺序进行排序

Array#sort 知道。该块只是告诉Array#sort 两个元素中的哪个“小于”另一个元素。就是这样。

换句话说:定义了“升序”的含义。

使用时也一样

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

它怎么知道这个块应该按降序排序?

不是按降序排列的。它按照块中实现的排序关系定义的升序顺序。

【讨论】:

    【解决方案3】:

    它是如何知道将“e”放在第一位,然后是“d”,然后是“c”

    从比较器块中,就是这样。在您自己的示例中:["a", "d"] (cmp result: -1)。这个 -1 告诉 sort "d" 应该在 "a" 之前。它稍后将"d""e" 进行比较,得到1 并得知"d" 应该在"e" 之后。以此类推。

    【讨论】:

      猜你喜欢
      • 2018-03-18
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 2017-06-10
      • 2012-11-08
      • 2023-03-07
      • 2012-12-21
      • 2018-04-25
      相关资源
      最近更新 更多