45

What's the fastest way in Ruby to get the first enumerable element for which a block returns true?

For example:

arr = [12, 88, 107, 500]
arr.select {|num| num > 100 }.first  # => 107

I'd like to do this without running through the entire array, as select will, since I only need the first match.

I know I could do an each and break on success, but I thought there was a native method for doing this; I just haven't found it in the documentation.

Nathan Long
  • 122,748
  • 97
  • 336
  • 451

3 Answers3

83

Several core ruby classes, including Array and Hash include the Enumerable module which provides many useful methods to work with these enumerations.

This module provides the find or detect methods which do exactly what you want to achieve:

arr = [12, 88, 107, 500]
arr.find { |num| num > 100 } # => 107

Both method names are synonyms to each other and do exactly the same.

Holger Just
  • 52,918
  • 14
  • 115
  • 123
  • Ah! `find` was the method I was trying to remember. Silly me, I was looking at the docs for `Array`, not `Enumerable`. – Nathan Long Mar 19 '12 at 13:13
  • 5
    also known in the Ruby world as `detect` – tokland Mar 19 '12 at 16:05
  • All hail to the synonyms. I personally prefer `find` (even more so when I'm not in a Rails environment). But you are are right, it might be better to generally use `detect` to un-confuse people. – Holger Just Mar 19 '12 at 19:02
  • 3
    Update - I always use the `detect` alias for this now. It's easy for me to remember `select reject detect` and doesn't get confused with ActiveRecord's `find`. – Nathan Long Jul 11 '13 at 15:49
3
arr.find{|el| el>100} #107 (or detect; it's in the Enumerable module.)
steenslag
  • 79,051
  • 16
  • 138
  • 171
0

I remember this using by thinking of ActiveRecord.find, which gets you the first record and ActiveRecord.select, which you use when you're getting all of them.

Not a perfect comparison but might be enough to help remember.

calasyr
  • 346
  • 2
  • 7