在块传递时,数组#sorting如何工作?

我有一个理解如何array.sort{ |x,y| block } 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"] 

在你的例子中

 a.sort 

相当于

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

正如你所知道的,为了对一个数组进行sorting,你需要能够比较它的元素(如果你怀疑的话,试着实现任何sortingalgorithm,而不使用任何比较,否则<><=>= )。

你提供的块实际上是一个函数,它将被sortalgorithm调用来比较两个项目。 那就是xy将始终是sortalgorithm在执行过程中所select的input数组的一些元素。

sortalgorithm将假定该比较函数/块将满足方法<=>的要求:

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

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

你现在应该明白为什么

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

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

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


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

  1. 你可以在你的类中包含Comparable模块,它会自动为你定义以下方法: between?==>=<<=>
  2. 你的类的实例现在可以使用缺省(即没有参数)调用进行sortsort

请注意,在ruby的标准库( BignumArrayFile::StatFixnumStringTime等等)中,已经提供了<=>方法。

当你有一个数组,比如sorting整数时, sort方法对于正确sort元素非常简单 – 首先是较小的数字,最后是较大的数字。 那是当你使用普通的sort ,没有阻止。

但是,当您sorting其他对象时,可能需要提供一种方法来比较(每个)其中两个。 假设你有一个Person类的对象数组。 你可能不知道对象bob是否比对象mike (即类Person没有方法<=>实现)更大。 在这种情况下,您需要提供一些代码来解释按照哪种顺序将这些对象sorting为sort方法。 这是块forms踢的地方。

 people.sort{|p1,p2| p1.age <=> p2.age} people.sort{|p1,p2| p1.children.count <=> p2.children.count} 

在所有这些情况下, sort方法以相同的方式对它们进行sort – 使用相同的algorithm。 比较逻辑有什么不同?

@OscarRyz的回复在我如何sorting的问题上为我解决了很多问题,

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

基于我的理解,我在这里提供了在每个比较上面的块结果之后数组的状态。

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

 1.9.3dev :001 > a = %w(deawfk) 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"] 

在每次比较之后,运行时的猜测数组状态:

  [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) 

谢谢,

Jignesh

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

  • -1如果self <argument
  • 0如果自我==参数
  • 1如果自我>论证

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

 array.sort{|x, y| some_very_complicated_method(x, y) } 

这里如果some_very_complicated_method(x,y)返回的是<0,则认为x <y,等等…

一些杂项点:

  • xy被称为块参数。 sorting方法基本上是这样说的:“我给你x和y,你决定是否应该先来个x或y,然后我会照顾无聊的东西,
  • <=>被称为飞船运营商 。

在:

 a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"] 

什么是x和y?

xy是通过sortingalgorithm进行比较的元素。

这对自定义类定义哪个元素应该在另一个之前是有用的。

对于基本数据(数字,string,date等),自然顺序是预先定义的,但是对于客户元素(即员工),您可以定义谁比谁先行。 这个块给你一个定义的机会。

在y <=> x上会发生什么?

在那里,他们按降序比较元素(那些具有“较高”值的元素将首先)而不是自然顺序( x<=>y

<=>方法代表“compareTo”,如果元素是等价的,则返回0;如果x先于y ,则返回< 0;如果x追随y ,则返回> 0

我相信| x,y | y <=> x是按照降序顺序比较两个元素,如下所示: http : //www.ruby-doc.org/core-1.9.3/Array.html#method-i-3C-3D- 3E用[“d”,“a”,“e”,“c”,“b”],“d”和“a”先比较一下。 然后,由于它下降,都保持在相同的顺序,因为D评估小于a。 然后评估d和e。 “e”移到“d”的位置。 不知道c代码的内部工作原理是不可能知道在哪里移动,但我认为这个过程继续下去,直到所有的元素sorting。 cfunction:

  VALUE rb_ary_cmp(VALUE ary1, VALUE ary2) { long len; VALUE v; ary2 = rb_check_array_type(ary2); if (NIL_P(ary2)) return Qnil; if (ary1 == ary2) return INT2FIX(0); v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2); if (v != Qundef) return v; len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2); if (len == 0) return INT2FIX(0); if (len > 0) return INT2FIX(1); return INT2FIX(-1); }