为什么Enumerable#find /#detect即使在Hash上调用也会返回一个数组?
Enumerable#find
/ #detect
的文档说:
find(ifnone = nil) { |obj| block } → obj or nil
find(ifnone = nil) → an_enumerator
将枚举中的每个条目传递给块 。 返回第一个块不为false的块。 如果没有对象匹配,则调用ifnone并在指定时返回其结果,否则返回
nil
。
但是,当在Hash上调用它时,结果将类型更改为Array而不是原始Hash。
是关于此数据类型的一些实现错误还是一些历史约定?
{a: 'a', b:'b'}.find {|k, v| v == 'b'} # => [:b, 'b']
Hash#detect
inheritance自Enumerable#detect
方法。
Enumerable
模块基于包含Enumerable
的类的each
方法生成多个方法(例如sort
, min
, max
包括detect
等)。
它并不关心each
方法的实施方式
“……产生了该集合的连续成员。”来自ruby-doc
所以对于Hash#detect
方法,它依赖于Hash#each
的行为,即:
对hsh中的每个键调用一次,将键值对作为参数传递。 如果没有给出块,则返回枚举器。
h = { "a" => 100, "b" => 200 } h.each {|key, value| puts "#{key} is #{value}" }
因为Hash#each
将哈希产生为两对数组,所以从Enumerable
模块inheritance的所有方法都基于此工作。
这就是为什么Hash#detect
产生一个两元素数组而不是一个哈希对象本身。
find
是根据each
。 each
在Hash上调用时,都返回数组forms的键值对,每个元素包含2个元素。 这就是为什么find
返回一个数组。
使用带有哈希的检测/查找
使用哈希,检测/查找将哈希中的每个键/值对传递给块,您可以将其“捕获”为:
一个双元素数组,键为元素0,其对应值为元素1或
h = {:a => 'a', :b => 'b'} p h.find {|k| pk ; 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”, aka “find”Enumerating Ruby's “Enumerable” Module, Part 3: “detect”, aka “find”