select filters elements
A method built to keep some, drop others
Lesson 6 of the last course ended on a pitfall: map can't skip an element, even when the block's logic looks like it should. select is built for that job.
numbers = [1, 2, 3, 4, 5]
evens = numbers.select { |n| n.even? }
evens # => [2, 4]
numbers # => [1, 2, 3, 4, 5], untouched
select calls the block once per element, like each and map, but keeps only the elements where the block returned something truthy. numbers is left alone, the "returns new, doesn't mutate" pattern the whole family follows.
The result can be any length, including zero
Here's the difference from map. map's result always has the input's length. select's result can be shorter, the same length, or empty.
numbers = [1, 3, 5]
numbers.select { |n| n.even? } # => [], nothing matched, and that's a valid result
An empty array from select isn't an error. It's a normal result meaning nothing matched.
Any truthy result keeps an element
names = ["Ada", "", "Grace", nil, "Kim"]
names.select { |name| name }
# => ["Ada", "", "Grace", "Kim"], the empty string survives; only nil was dropped
select keeps an element whenever the block's result is truthy, the rule from Ruby logic: standard checks. Only nil and false are falsy. Everything else is truthy and kept, including the empty string "", which is why it survives above. "" is falsy in many other languages, but not in Ruby. The block doesn't need to return true or false; any expression works.
Key takeaways
selectkeeps the elements where the block is truthy and leaves the original untouched.- Unlike
map's,select's result can be shorter than the input, or empty. - An empty result means nothing matched; it isn't an error.
- Any truthy result keeps an element; the block needn't return
trueorfalse.
Keep going with lesson 2
select vs map vs each
Compares each, map and select, and shows filtering with select before transforming with map.
A free account also gives you the quizzes, your progress and notes, and the discussion.