“find_all”和“select”是一回事吗?

时间:2014-01-08 15:03:23

标签: ruby

这两个陈述给出了相同的结果:

[1,2,3,4].find_all { |x| x.even? }

[1,2,3,4].select{ |x| x.even? }

find_all只是一个别名吗?是否有理由使用另一个?

3 个答案:

答案 0 :(得分:61)

#find_all#select非常相似;差异非常微妙。在大多数情况下,它们是等价的。这取决于实现它的类。

Enumerable#find_allEnumerable#select运行相同的代码。

ArrayRange也是如此,因为它们使用Enumerable实现。

对于Hash#select被重新定义为返回哈希而不是数组,但#find_all继承自Enumerable

a = [1, 2, 3, 4, 5, 6]
h = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}

a.select{|x| x.even?}       # => [2, 4, 6]
a.find_all{|x| x.even?}     # => [2, 4, 6]

h.select{|k,v| v.even?}     # => {:b=>2, :d=>4, :f=>6}
h.find_all{|k,v| v.even?}   # => [[:b, 2], [:d, 4], [:f, 6]]

答案 1 :(得分:16)

Enumerable#find_all 返回一个数组,其中包含给定块返回真值的枚举的所有元素,而select不是这种情况。 Enumerable#select会返回Array,如果您正在调用的接收方为#select方法,则不会拥有自己的#select方法。否则,在您调用#select方法的接收器上,它将在处理块条件后返回相似类型的接收器。

Like Hash#select 返回一个新的哈希,该哈希由块返回的条目true Array#select 返回一个包含所有元素的新数组给定块返回真值的ary。现在Range#select将返回Array,因为Range类没有自己的实例方法{{ {1}}。而不是#select,它会调用Enumerable#select

Enumerable

这是一个完整的演示,示例有利于我上面的解释:

rng = (1..4)
ary = [1,2]
hsh = {:a => 1}

rng.method(:select) # => #<Method: Range(Enumerable)#select>
hsh.method(:select) # => #<Method: Hash#select>
ary.method(:select) # => #<Method: Array#select>

答案 2 :(得分:8)

是的,对于Arrays,它们会返回相同的结果。对于其他事物(例如哈希),他们可能会返回不同的东西。

根据selectfind_all的可枚举文档,两种方法都指向相同的源代码,并且都返回一个数组(如果给出一个块)或一个枚举器(如果没有块)给出了。)

虽然Array类实现了自己的select版本(但允许Enumerable句柄find_all),但它们仍然会做同样的事情。