select, reject, find and detect in Ruby
Short answer
select keeps every item where the block is true, reject keeps every item where it is false, and find returns only the first match and stops.
nums = [4, 8, 15, 16, 23, 42]
nums.select { |n| n.even? } # [4, 8, 16, 42]
nums.reject { |n| n.even? } # [15, 23]
nums.find { |n| n > 10 } # 15 — a single value, not an array
nums.count { |n| n > 10 } # 4find stops at the first match, so it is much cheaper than select(...).first on a large collection.
#Aliases you will see
selectis alsofilterfindis alsodetectreduceis alsoinjectcollectismap
Modern style prefers select, find, reduce and map. The aliases exist for historical reasons and turn up in older code.
#Predicate methods read well here
nums.select(&:even?)
nums.reject(&:zero?)#Related tests
nums.any? { |n| n > 40 } # true
nums.all? { |n| n > 0 } # true
nums.none? { |n| n > 100 } # true
nums.one? { |n| n == 42 } # trueAll of them short-circuit — any? stops at the first true, all? at the first false.
#filter_map, when you would chain two
videos.select { |v| v[:views] > 200 }.map { |v| v[:title] }
videos.filter_map { |v| v[:title] if v[:views] > 200 }One pass instead of two, and no intermediate array.
#partition, when you want both halves
popular, quiet = videos.partition { |v| v[:views] > 200 }