当块传递时,Array#sort如何工作?

Ibr*_*ein 74 ruby arrays sorting

我有一个问题,了解如何array.sort{ |x,y| block }正常工作,因此如何使用它?

Ruby文档中的一个示例:

   a = [ "d", "a", "e", "c", "b" ]
   a.sort                     #=> ["a", "b", "c", "d", "e"]
   a.sort { |x,y| y <=> x }   #=> ["e", "d", "c", "b", "a"]
Run Code Online (Sandbox Code Playgroud)

blt*_*txd 121

在你的例子中

a.sort
Run Code Online (Sandbox Code Playgroud)

相当于

a.sort { |x, y| x <=> y }
Run Code Online (Sandbox Code Playgroud)

如你所知,对数组排序,你需要能够比较它的元素(如果你怀疑,只是试图实现任何排序算法,而无需使用任何比较,没有<,>,<=>=).

您提供的块实际上是一个函数,sort算法将调用该函数来比较两个项目.这是x并且y将始终是sort算法在执行期间选择的输入数组的一些元素.

sort算法将假设这种比较功能/块将满足方法的要求<=>:

  • 如果x <y则返回-1
  • 如果x = y则返回0
  • 如果x> y则返回1

如果未能提供足够的比较函数/块,将导致数组的顺序未定义.

你现在应该明白为什么

a.sort { |x, y| x <=> y }
Run Code Online (Sandbox Code Playgroud)

a.sort { |x, y| y <=> x }
Run Code Online (Sandbox Code Playgroud)

以相反的顺序返回相同的数组.


要详细说明Tate Johnson添加的内容,如果您<=>在任何类上实现比较功能,您将获得以下内容

  1. 您可以包括模块Comparable中的类,它会自动为您定义了以下方法:between?,==,>=,<,<=>.
  2. 现在可以使用默认(即不带参数)调用来对类的实例进行排序sort.

需要注意的是,<=>已经提供的方法,只要它使在Ruby的标准库感(Bignum,Array,File::Stat,Fixnum,String,Time,等...).


Mla*_*vić 21

当你有一个数组,比如整数排序时,对于sort正确排序元素的方法来说非常简单- 首先是较小的数字,最后是较大的数字.那是你使用普通的时候sort,没有阻挡.

但是当您对其他对象进行排序时,可能需要提供一种比较(每个)两个对象的方法.假设你有一个类对象数组Person.您可能无法判断对象bob是否大于对象mike(即类Person没有<=>实现方法).在这种情况下,您需要提供一些代码来解释您希望将这些对象排序到sort方法的顺序.这就是阻碍形成的地方.

people.sort{|p1,p2| p1.age <=> p2.age}
people.sort{|p1,p2| p1.children.count <=> p2.children.count}
Run Code Online (Sandbox Code Playgroud)

在所有这些情况下,sort方法以相同的方式对它们进行排序 - 使用相同的算法.不同的是比较逻辑.


Jig*_*hel 8

@OscarRyz的回复在关于排序如何运作的问题上为我清理了很多,尤其是

 { |x, y| y <=> x }
Run Code Online (Sandbox Code Playgroud)

根据我的理解,我在这里提供了在上述块结果的每次比较之后数组的状态.

注意:参考了从ruby-forum打印块参数e1,e2的值

1.9.3dev :001 > a = %w(d e a w f k)
1.9.3dev :003 > a.sort { |e1, e2| p [e2, e1]; e2 <=> e1 }
["w", "d"]
["k", "w"]
["k", "d"]
["k", "e"]
["k", "f"]
["k", "a"]
["f", "a"]
["d", "f"]
["d", "a"]
["d", "e"]
["e", "f"]
 => ["w", "k", "f", "e", "d", "a"]
Run Code Online (Sandbox Code Playgroud)

每次比较后运行时猜到的数组状态:

 [e2, e1]    Comparsion Result       Array State
["w", "d"]      1                   ["w", "e", "a", "d", "f", "k"]
["k", "w"]     -1                   ["w", "e", "a", "d", "f", "k"]
["k", "d"]      1                   ["w", "e", "a", "k", "f", "d"]
["k", "e"]      1                   ["w", "k", "a", "e", "f", "d"]  
["k", "f"]      1                   ["w", "k", "a", "e", "f", "d"]    
["k", "a"]      1                   ["w", "k", "a", "e", "f", "d"]  
["f", "a"]      1                   ["w", "k", "f", "e", "a", "d"]  
["d", "f"]     -1                   ["w", "k", "f", "e", "a", "d"]  
["d", "a"]      1                   ["w", "k", "f", "e", "d", "a"]  
["d", "e"]     -1                   ["w", "k", "f", "e", "d", "a"]  
["e", "f"]     -1                   ["w", "k", "f", "e", "d", "a"] (Result)
Run Code Online (Sandbox Code Playgroud)

谢谢,

Jignesh


Dra*_*ter 7

<=>是一个方法是ruby返回(self.<=>( argument ))

  • -1如果自己<参数
  • 0如果self ==参数
  • 1如果自我>参数

x并且y是数组的项目.如果没有提供块,则sort函数使用x<=>y,否则块的结果表示x应该在y之前.

array.sort{|x, y| some_very_complicated_method(x, y) }
Run Code Online (Sandbox Code Playgroud)

这里,如果some_very_complicated_method(x,y)返回<0的smth,则x被视为<y,依此类推......