Labs ICT
โญ Pro Login

The Enumerable Module

Powerful iteration built into Ruby.

The Enumerable Module

Enumerable is one of Ruby's most powerful modules. When you define a single method called each, you automatically get access to dozens of methods: map, select, reject, sort, min, max, and many more. This is the magic of Ruby's design โ€” define one thing, get everything.

class WordCollection
  include Enumerable

  def initialize(words)
    @words = words
  end

  def each(&block)
    @words.each(&block)
  end
end

words = WordCollection.new(["apple", "banana", "cherry", "date"])

# All these work automatically:
puts words.map(&:length).inspect     # => [5, 6, 6, 4]
puts words.select { |w| w.start_with?("b") }.inspect  # => ["banana"]
puts words.sort.inspect              # => ["apple", "banana", "cherry", "date"]
puts words.min                       # => "apple"
puts words.max                       # => "date"
puts words.any? { |w| w.length > 5 } # => true
puts words.count                     # => 4
Try it Yourself ->

Enumerable is Everywhere

Array, Hash, and Range all include Enumerable. That's why you can use map on a hash, select on a range, and sort on an array. They all define each, which gives them everything.

# Array includes Enumerable
puts [3, 1, 2].sort.inspect       # => [1, 2, 3]
puts [1, 2, 3, 4].select(&:even?).inspect  # => [2, 4]

# Hash includes Enumerable
hash = { a: 1, b: 2, c: 3 }
puts hash.map { |k, v| "#{k}=#{v}" }.inspect
# => ["a=1", "b=2", "c=3"]

# Range includes Enumerable
puts (1..10).select(&:odd?).inspect  # => [1, 3, 5, 7, 9]
puts (1..5).reduce(:+)              # => 15
Try it Yourself ->

Custom Enumerable: Build Your Own

You can create your own Enumerable class. Define each, and you get map, select, sort, min, max, group_by, partition, and dozens more for free. One method, endless possibilities.

class Fibonacci
  include Enumerable

  def initialize(limit)
    @limit = limit
  end

  def each
    a, b = 0, 1
    while a <= @limit
      yield a
      a, b = b, a + b
    end
  end
end

fib = Fibonacci.new(100)

puts fib.select(&:even?).inspect
# => [0, 2, 8, 34]

puts fib.map { |n| n * 2 }.inspect
# => [0, 2, 2, 6, 10, 16, 26, 42, 68, 110]

puts fib.max  # => 89
puts fib.min  # => 0
Try it Yourself ->

Enumerable Methods You'll Use

Here are the most commonly used Enumerable methods. Once you internalize these, you'll write Ruby code that reads like English.

data = [5, 3, 8, 1, 9, 2, 7]

# Finding things
puts data.find { |n| n > 6 }         # => 8 (first match)
puts data.select { |n| n.odd? }.inspect  # => [5, 3, 1, 9, 7]
puts data.reject { |n| n > 5 }.inspect   # => [5, 3, 1, 2]

# Aggregating
puts data.reduce(:+)                 # => 35
puts data.min                        # => 1
puts data.max                        # => 9
puts data.sum                        # => 35

# Transforming
puts data.map { |n| n * 10 }.inspect  # => [50, 30, 80, 10, 90, 20, 70]
puts data.sort.inspect               # => [1, 2, 3, 5, 7, 8, 9]
puts data.reverse.inspect            # => [7, 2, 9, 1, 8, 3, 5]

# Checking
puts data.any? { |n| n > 8 }        # => true
puts data.all? { |n| n > 0 }        # => true
puts data.none? { |n| n < 0 }       # => true
puts data.include?(5)               # => true
Try it Yourself ->

The Power of One Method

This is Ruby's philosophy in action. Instead of giving you a hundred methods to implement, Ruby says: just define each, and we'll handle the rest. It's elegant, DRY, and powerful. When you truly understand Enumerable, you understand what makes Ruby special.

class Primes
  include Enumerable

  def initialize(count)
    @count = count
  end

  def each
    n = 2
    yielded = 0
    while yielded < @count
      yield n if prime?(n)
      yielded += 1 if prime?(n)
      n += 1
    end
  end

  private

  def prime?(n)
    return false if n < 2
    (2..Math.sqrt(n)).none? { |i| n % i == 0 }
  end
end

primes = Primes.new(10)
puts primes.inspect              # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
puts primes.select { |p| p > 10 }.inspect  # => [11, 13, 17, 19, 23, 29]
puts primes.map { |p| p * 2 }.inspect      # => [4, 6, 10, 14, 22, 26, 34, 38, 46, 58]
Try it Yourself ->

๐Ÿงช Quick Quiz

What module gives you free iteration methods?