Often, Enumerable#select is the chosen method to obtain elements from an Array for a given block. Without thinking twice, we may be doing more work than necessary by not taking advantage of another method from the Enumerable module, Enumerable#grep .

Enumerable#grep can not always be used instead of Enumerable#select , but when it can, #grep provides better readability and a small speed improvement over #select .

See the benchmark below for example, which uses the class matcher for #grep :

2 . 1 . 2 : 041 > a = ( 1 .. 100000 ) . map { rand ( 100000 ) } 2 . 1 . 2 : 042 > b = ( 1 .. 100000 ) . map { rand ( 100000 ) . to_s } 2 . 1 . 2 : 043 > c = a + b 2 . 1 . 2 : 044 > Benchmark . bm ( 10 ) do | b | 2 . 1 . 2 : 045 > b . report ( "select" ) { c . select { | x | x . is_a? Integer } } 2 . 1 . 2 : 046 ?> b . report ( "grep" ) { c . grep ( Integer ) } 2 . 1 . 2 : 047 ?> end user system total real select 0 . 040000 0 . 000000 0 . 040000 ( 0 . 0377 99 ) grep 0 . 020000 0 . 000000 0 . 020000 ( 0 . 02374 9 ) 2 . 1 . 2 : 04 8 > c . select { | x | x . is_a? Integer } == c . grep ( Integer ) => true

You can also see its power when using Regexp patterns, which is not only faster but also less verbose, which is enough of a win to favor it over #select :

2 . 1 . 2 : 04 9 > a = ( 1 .. 100000 ) . map { ( 65 + rand ( 26 )) . chr } 2 . 1 . 2 : 050 > b = ( 1 .. 100000 ) . map { rand ( 10 ) . to_s } 2 . 1 . 2 : 051 > c = a + b 2 . 1 . 2 : 052 > Benchmark . bm ( 10 ) do | b | 2 . 1 . 2 : 053 > b . report ( "select" ) { c . select { | x | /^\d*$/ === x } } 2 . 1 . 2 : 054 ?> b . report ( "grep" ) { c . grep ( /^\d*$/ ) } 2 . 1 . 2 : 055 ?> end user system total real select 0 . 020000 0 . 000000 0 . 020000 ( 0 . 02105 8 ) grep 0 . 020000 0 . 000000 0 . 020000 ( 0 . 012626 )

There are some pretty good use cases for #grep , and one last thing worth keeping in mind: #grep can take a second parameter, which acts as #map does and reads very nicely. For example: