我理解#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
的示例对于一组数字会有什么行为?
答案 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
返回的值为max
。 minmax
,sort
和min_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
的块的结果。 max
,minmax
和C:\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
将两个元素a
和b
从数组传递到块,预计块将返回-1
,0
或{{ 1}}取决于+1
是否小于,等于或大于a
。 &#34;宇宙飞船&#34;运算符b
会返回这些<=>
,-1
或0
值。
算法很简单。给定比较函数:
+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'