Array#select
arr.select { |element| block } -> new_array Array#select filters array elements based on a condition you define in a block. It returns a new array containing only the elements for which the block evaluates to truthy. This is one of the most common methods for extracting subsets of data from arrays.
The key thing to remember: select only includes elements where the block returns a truthy value (true or anything other than nil or false). It never modifies the original array.
That makes select a natural fit for questions like “Which items should stay?” or “Which values meet this rule?” It is easy to chain with other methods, and it keeps the selection logic in one place instead of spreading it across a manual loop. When the goal is to keep a subset and leave the original untouched, select is usually the clearest choice.
You will often see select paired with methods like map, count, or first, because it gives you a smaller collection to work with before the next step. That keeps the pipeline readable and avoids manual indexing or mutation in the middle of the transformation.
Another practical benefit is that the block expresses the rule directly in code. A future reader does not have to reverse engineer a loop or remember which indexes were skipped, because the condition sits right next to the list that is being filtered.
Syntax
array.select { |element| block }
array.select # without block returns an Enumerator
When you omit the block, select returns an Enumerator, which lets you chain other Enumerable methods or use it with control flow structures.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
block | Proc | Required | A block that receives each element. Return truthy to include the element, falsy to exclude it. |
Return Value
Returns a new Array containing all elements for which the block returned a truthy value. The original array remains unchanged. Returns an empty array if no elements match.
Examples
Basic filtering
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Get only even numbers
evens = numbers.select { |n| n.even? }
# => [2, 4, 6, 8, 10]
# Get numbers greater than 5
greater_than_five = numbers.select { |n| n > 5 }
# => [6, 7, 8, 9, 10]
The first example keeps elements based on a simple predicate, and the same pattern transfers directly to string collections without changing the method signature. Working with strings introduces its own set of predicates, like checking length or looking for substrings, but the shape of the code stays the same: pass a block, get a filtered array back. That consistency is part of why Ruby developers reach for select so often—the mental model does not shift between data types, only the condition does.
Filtering strings
words = ["apple", "banana", "cherry", "date", "elderberry"]
# Get words longer than 5 characters
long_words = words.select { |w| w.length > 5 }
# => ["banana", "cherry", "elderberry"]
# Get words containing the letter 'a'
has_a = words.select { |w| w.include?('a') }
# => ["apple", "banana", "date"]
Once you are comfortable filtering by string properties, it is a short step to filtering by numeric ranges. The between? method gives you a clean way to express an inclusive boundary without writing two separate comparisons, and select pairs naturally with it because the condition reads like a yes-or-no question about each element. Range checks also help when you want to narrow a collection to values that fall inside a known window, such as dates, scores, or index positions.
Filtering with ranges
numbers = [1, 5, 10, 15, 20, 25, 30]
# Select numbers in a specific range
in_range = numbers.select { |n| n.between?(10, 20) }
# => [10, 15, 20]
Range checks are a tidy example because the condition is easy to read and easy to change later. If the bounds move, you only update the block, not the surrounding control flow.
See Also
- Array#find — returns the first element that matches
- Array#map — transforms each element