"find_all"和"select"是一回事吗?

ek_*_*_ny 30 ruby

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

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

[1,2,3,4].select{ |x| x.even? }
Run Code Online (Sandbox Code Playgroud)

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

wac*_*cko 66

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

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

对于ArrayRange使用Enumerable实现的情况也是如此.

在这种情况下Hash,#select重新定义为返回Hash而不是Array,但#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]]
Run Code Online (Sandbox Code Playgroud)


Aru*_*hit 16

Enumerable#find_all 返回一个数组,其中包含给定块返回true值的枚举的所有元素,但不是这种情况select.Enumerable#select返回Array,如果您所呼叫的接收#select方法,没有它自己的#select方法.否则,在您调用哪个接收#select方法时,它将在处理块条件后返回类似类型的接收器.

Like 返回一个新的哈希,该哈希由块返回的条目组成,返回一个新数组,其中包含给定块返回true值的所有ary元素.现在将给你返回一个,因为类没有自己的实例方法调用.而不是一个,它会打电话.Hash#select trueArray#select Range#selectArrayRange#selectEnumerableEnumerable#select

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>
Run Code Online (Sandbox Code Playgroud)

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

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

# Look find_all always gives Array.
hsh.find_all{ true } # => [[:a, 2], [:b, 3]]
ary.find_all{ true } # => [1, 2, 3]
rng.find_all{ true } # => [1, 2, 3]

# Look select not giving Array always, explanation of why so is written
# above in my answer.
hsh.select{ true } # => {:a=>2, :b=>3}
ary.select{ true } # => [1, 2, 3]
rng.select{ true } # => [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

  • 我认为你应该提供一个例子,表明一般来说,`select`和`find_all`的行为不一样. (2认同)

Dyl*_*kow 8

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

根据selectfind_all的Enumerable文档,两种方法都指向相同的源代码,并且都返回一个Array(如果给出一个块)或一个Enumerator(如果没有给出块).

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

  • *可枚举(如果没有给出块)*也是错误的..它是*枚举器*,而不是"可枚举". (2认同)