Ruby组合比较运算符(< =>)和min / max / minmax函数

时间:2015-09-04 20:29:45

标签: ruby max min logical-operators minmax

我理解#max,#min,#minmax。我理解< =>。但是它如何在其中一个函数中的块中起作用?

那就是,下面第三行发生了什么?什么是< =>在#min做什么?

a = %w(albatross dog horse)
a.min                                   #=> "albatross"
a.min { |a, b| a.length <=> b.length }  #=> "dog"

来自http://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-min

的示例

对于一组数字会有什么行为?

2 个答案:

答案 0 :(得分:4)

正如您可能已经看到的那样,min方法的the documentation说:

  

<强> min(n) → array

     

<强> min(n) {| a,b | block } → array

     

返回枚举中具有最小值的对象。第一种形式   假设所有对象都实现Comparable;第二个使用块来   返回a <=> b

这意味着,在第一种形式中,min在数组中的对象上调用<=>方法,并使用结果来确定哪个元素是最小的。

在第二种形式中,min用它想要比较的两个元素调用,并使用块的返回值来确定哪个元素是最小。基本上,它使用块就好像它是<=>运算符的实现一样。因此x.min {|a,b| a <=> b }等同于x.min

在给定的示例(a.min { |a, b| a.length <=> b.length } #=> "dog")中,这意味着它不是比较每个元素来确定排序顺序,而是比较每个元素的长度以进行确定。由于"dog"是列表中最短的字符串,因此min返回的值为maxminmaxsortmin_by行为相似。

请注意,这个示例有点人为,因为您可以在这种情况下使用a.min_by { |x| x.length }来使用更简单的代码获得相同的结果:min。如果您在确定排序顺序时需要更细粒度的控制,则使用带有块的min可能是合适的。

  

对于一组数字会有什么行为?

无论数组包含什么,

{ |a, b| a.length <=> b.length }的行为方式都相同。在这种情况下,虽然使用块length不会起作用,因为数字上没有[2, 10, 9, 7, 6, 1, 5, 3, 8, 4].sort do |a, b| if a.odd? && b.even? 1 elsif a.even? && b.odd? -1 else a <=> b end end 方法。这是数字的一个更好的例子,它按从最小到最大排序,但总是将奇数计为大于偶数:

[2, 4, 6, 8, 10, 1, 3, 5, 7, 9]

结果:

sort

注意偶数在最终数组中的奇数之前是如何排序的?这是我们传递给min的块的结果。 maxminmaxC:\Users\James>sqlite3 test SQLite version 3.8.3.1 2014-02-11 14:52:19 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> create table dashboard ( data, title ); sqlite> .schema CREATE TABLE dashboard ( data, title ); sqlite> insert into dashboard ( "test","TEMPLATE"); sqlite> update dashboard set data= ...> '{"annotations":{"list":[]},"editable":true,"hideControls":false,"id":30, ...> "nav":[{"collapse":false,"enable":true,"notice":false,"now":false, ...> "refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"], ...> "status":"Stable", ...> "time_options":["5m","15m","1h","6h","12h","24h","2d","7d","30d"],"type":"timepicker"}]}' ...> where where title='TEMPLATE'; Error: near "where": syntax error sqlite> update dashboard set data= ...> '{"annotations":{"list":[]},"editable":true,"hideControls":false,"id":30, ...> "nav":[{"collapse":false,"enable":true,"notice":false,"now":false, ...> "refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"], ...> "status":"Stable", ...> "time_options":["5m","15m","1h","6h","12h","24h","2d","7d","30d"],"type":"timepicker"}]}' ...> where title='TEMPLATE'; sqlite> select * from dashboard; {"annotations":{"list":[]},"editable":true,"hideControls":false,"id":30, "nav":[{"collapse":false,"enable":true,"notice":false,"now":false, "refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"], "status":"Stable", "time_options": ["5m","15m","1h","6h","12h","24h","2d","7d","30d"],"type":"timepicker"}]}|TEMPLATE 的行为类似。

答案 1 :(得分:2)

min将两个元素ab从数组传递到块,预计块将返回-10或{{ 1}}取决于+1是否小于,等于或大于a。 &#34;宇宙飞船&#34;运算符b会返回这些<=>-10值。

算法很简单。给定比较函数:

+1

我们首先将第1个元素与第2个元素进行比较:

cmp = -> (a, b) { a.length <=> b.length }

cmp.call 'albatros', 'dog' #=> 1 表示1大于'albatros'。我们继续使用较小的值,即'dog'并将其与第3个元素进行比较:

'dog'

cmp.call 'dog', 'horse' #=> -1 表示-1小于'dog'。没有更多元素,因此'horse'就是结果。

您也可以在Ruby中实现此算法:

'dog'