ek_ny
ek_ny

Reputation: 10243

Is "find_all" and "select" the same thing?

These two statements give me the same results:

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

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

Is find_all just an alias? Is there a reason to use one over another?

Upvotes: 35

Views: 22510

Answers (4)

#find_all

with array it returns result as array

with hash it returns result as array


select

with array it returns result as array

with hash it returns result as hash


Upvotes: -1

Arup Rakshit
Arup Rakshit

Reputation: 118289

Enumerable#find_all Returns an array containing all elements of enum for which the given block returns a true value, which is not the case for select. Enumerable#select returns the Array, if the receiver on which you are calling #select method, don't have it's own #select method. Otherwise on which receiver you are calling #select method, it will return similar type of receiver, after processing the block condition.

Like Hash#select Returns a new hash consisting of entries for which the block returns true and Array#select Returns a new array containing all elements of ary for which the given block returns a true value. Now Range#select will give you return back an Array, as Range class don't have its own instance method called #select. Rather being an Enumerable,it will call Enumerable#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>

Here is a full demonstration with example in-favor of my explanation above :

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]

Upvotes: 16

Dylan Markow
Dylan Markow

Reputation: 124439

Yes, for Arrays, they return identical results. For other things (e.g. Hashes), they may return different things.

According to the Enumerable documentation for select and find_all, both methods point to the same source code, and both return either an Array (if a block is given) or an Enumerator (if no block is given).

While the Array class implements its own version of select (but lets Enumerable handle find_all), they still do the same thing.

Upvotes: 8

wacko
wacko

Reputation: 3424

#find_all and #select are very similar; the difference is very subtle. In most of the cases, they are equivalent. It depends on the class implementing it.

Enumerable#find_all and Enumerable#select run on the same code.

The same happens for Array and Range, as they use Enumerable implementation.

In the case of Hash, #select is redefined to return a Hash instead of an Array, but #find_all is inherited from 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]]

Upvotes: 69

Related Questions