The Enumerable
module provides numerous useful methods for working with collections, such as arrays, hashes, and ranges.
Any object that includes Enumerable
means you can easily go through each item in that collection and use helpful methods like map
, select
, and find
.
For example, arrays include Enumerable
, so you can use these methods to transform, filter, or search through their elements.
Let's use the map
method (one of the Enumerable
methods) to double each number in an array:
numbers = [1, 2, 3, 4, 5]
# Double each number
doubled = numbers.map { |n| n * 2 }
puts doubled
# Output: [2, 4, 6, 8, 10]
The map
method takes each item from the array, changes it based on the code inside the block.
Here, { |n| n * 2 }
is a code block that you pass to the map
method.
|n|
represents each item in the array.n * 2
tells Ruby how to change that item by doubling it.
Common Enumerable Methods
You've already worked with the map
method in the previous example. Besides map
, several other common Enumerable
methods are useful when working with collections in Ruby.
Here's a quick overview of some of the most popular ones:
Method | Description |
---|---|
each |
Goes through each item one by one. |
select |
Picks items that match a condition. |
find |
Finds the first item that matches a condition. |
reduce |
Combines all items into a single value. |
The each Method
The each
method goes through every item in a collection one by one and runs the code for each item. For example,
numbers = [1, 2, 3, 4, 5]
numbers.each { |n| p n }
# Print the numbers array
p numbers
Output
1 2 3 4 5 [1, 2, 3, 4, 5]
In this example, each
executes the block of code for every number in the array. The p n
command prints each number.
Since each
doesn't change the original collection, the numbers
array stays the same.
The select Method
The select
method filters the collection by keeping only the items that match a condition you specify. For example,
numbers = [1, 2, 3, 4, 5]
evens = numbers.select { |n| n.even? }
p evens
Output
[2, 4]
In this example, the select
method goes through each number in the array and keeps only the ones where the condition n.even?
is true
.
The find Method
The find
method looks for the first item that matches a condition you provide. It stops searching as soon as it finds one.
For example,
numbers = [1, 2, 3, 4, 5]
first_big = numbers.find { |n| n > 3 }
puts first_big
Output
4
Here, the find
method returns the first number greater than 3, which is 4.
The reduce Method
The reduce
method combines all items in a collection into a single value by applying your block repeatedly. For example,
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |total, n| total + n }
puts sum
Output
15
In this example, the reduce
method combines all the numbers in the array into a single value — the total sum
.
The 0 inside reduce(0)
is the starting value for the calculation (called the "initial accumulator").
The block { |total, n| total + n }
takes two parameters:
Parameter | Description |
---|---|
total |
Keeps track of the running total as the method goes through the array |
n |
The current number from the array being used |
For each number, it adds n
to total
, updating the sum
step by step.
After going through all numbers, the reduce
method returns the final sum
.
Frequently Asked Questions
You've seen how you can use the Enumerable
methods like map
or select
with arrays.
In Ruby, to use Enumerable
methods on a collection, the collection's class must have an each
method defined. This each
method tells Ruby how to loop over the items one by one.
For example, the Array
class already has an each
method built-in, which is why you can easily use Enumerable
methods with arrays.
But what if you create your own collection class? It won't have an each
method by default, so you can't use Enumerable
methods on it yet.
Let's define our own class, add an each
method to it, and then try out Enumerable
methods:
class MyCollection
include Enumerable # Bring in Enumerable methods
def initialize(items)
@items = items
end
def each
@items.each do |item|
yield item # Pass each item to the block
end
end
end
collection = MyCollection.new([1, 2, 3, 4, 5])
doubled = collection.map { |n| n * 2 }
p doubled
Output
[2, 4, 6, 8, 10]
Here, we defined the each
method inside the MyCollection
class. Now, we can use Enumerable
methods like map
with our custom collection.
Using Enumerable with a Range
You can also use enumerable methods on a range. For example,
# Define a range from 1 to 10
numbers = (1..10)
# Use select to pick only even numbers
evens = numbers.select { |n| n.even? }
p evens
Output
[2, 4, 6, 8, 10]
Here, the range (1..10)
behaves like a collection of numbers from 1 to 10. We use select
(an Enumerable
method) to filter and keep only even numbers.
Using Enumerable with a Hash
You can also use the Enumerable
method like select
to filter key-value pairs in hashes. For example,
# Define a hash of fruits with their quantities
fruits = { apple: 3, banana: 5, orange: 2, mango: 4 }
# Select fruits with quantity greater than 3
big_fruits = fruits.select { |fruit, qty| qty > 3 }
p big_fruits
Output
{banana: 5, mango: 4}
Here, the select
method iterates through each key-value pair and keeps only those where the quantity is more than 3.
Why use Enumerable?
Some reasons why Enumerable
is so useful:
- Saves time by eliminating the need to write loops manually.
- Makes your code shorter, cleaner, and easier to understand.
- Offers flexible and powerful tools for a wide range of data tasks.
- Works seamlessly with arrays, hashes, ranges, and even your custom collections.