Ruby Enumerable

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

How Enumerable Works?

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.

Did you find this article helpful?

Our premium learning platform, created with over a decade of experience and thousands of feedbacks.

Learn and improve your coding skills like never before.

Try Programiz PRO
  • Interactive Courses
  • Certificates
  • AI Help
  • 2000+ Challenges