为什么Enumerable#find /#detect即使在Hash上调用也会返回一个数组?

时间:2013-04-27 10:03:33

标签: ruby arrays hash enumerable

documentation for Enumerable#find/#detect说:

  

find(ifnone = nil) { |obj| block } → obj or nil
find(ifnone = nil) → an_enumerator

     

enum 中的每个条目传递给返回哪个块的第一个   不是假的。如果没有对象匹配,则调用 ifnone 并返回它   指定时的结果,否则返回nil

但是,当在Hash上调用它时,结果将类型更改为Array而不是原始Hash。

是否存在某些实现错误或有关此数据类型的一些历史约定?

{a: 'a', b:'b'}.find {|k, v| v == 'b'}
# => [:b, 'b']

3 个答案:

答案 0 :(得分:5)

Hash#detect继承自Enumerable#detect方法。

Enumerable模块基于sort方法生成多个方法(例如minmaxdetect,包括each等)该课程包括Enumerable

它不关心each的实施方式,只要它

  

“......产生该系列的连续成员。”   来自ruby-doc

因此对于Hash#detect方法,它依赖于Hash#each的行为,即:

  

为hsh中的每个键调用一次阻塞,将键值对传递为   参数。如果没有给出块,则返回枚举器。

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }

因为Hash#each将哈希产生为两对数组,所以从Enumerable模块继承的所有方法都基于此工作。

这就是Hash#detect生成两个元素数组而不是散列对象本身的原因。

答案 1 :(得分:4)

find是根据each实施的。并且each在Hash上调用时,以数组的形式返回键值对,每个元素包含2个元素。这就是find返回数组的原因。

答案 2 :(得分:0)

使用带有哈希的检测/查找

使用哈希,detect / find将散列中的每个键/值对传递给块,您可以将其“捕获”为:

一个双元素数组,键为元素0,其对应值为元素1,

h = {:a => 'a', :b => 'b'}
p h.find {|k| p k ; k[1] == 'b'}

输出:

[:a, "a"]
[:b, "b"]
[:b, "b"]

两个单独的项目,其中键作为第一个项目,相应的值作为第二个项目。

h = {:a => 'a', :b => 'b'}
p h.find {|k, v| puts k,v ; v == 'b'}

输出:

a
a
b
b
[:b, "b"]

要了解有关此主题的更多信息,请查看Enumerating Ruby’s “Enumerable” Module, Part 3: “detect”, a.k.a. “find”Enumerating Ruby’s “Enumerable” Module, Part 3: “detect”, a.k.a. “find”