Ruby Enumerables

This chapter explores Ruby Enumerables, a powerful module that provides a collection of iteration and search methods for classes that include it. Enumerables allow for concise and expressive code when working with collections like arrays, hashes, and ranges.

Chapter Goals

  • Understand the purpose and usage of the Enumerable module in Ruby.
  • Learn about common enumerable methods such as map, select, reject, and reduce.
  • Explore how to implement custom enumerables by including the Enumerable module.
  • Implement best practices for leveraging enumerables effectively in Ruby.

Key Characteristics of Ruby Enumerables

  • Iterative Methods: Provide a variety of methods for traversing and manipulating collections.
  • Chained Operations: Methods can be chained for expressive and concise code.
  • Custom Enumerables: Allows the creation of custom classes with enumerable functionality.
  • Consistency: Follows a unified approach across different collection types.

Basic Rules for Enumerables

  • Use include Enumerable in a class to gain access to enumerable methods.
  • Define an each method in the class to make it compatible with Enumerable.
  • Use built-in enumerable methods to simplify iteration and manipulation tasks.

Best Practices

  • Use descriptive variable names in enumerable blocks for clarity.
  • Combine enumerable methods to write concise and expressive code.
  • Prefer enumerables over manual loops for better readability and maintainability.
  • Avoid chaining too many methods in a single expression to maintain readability.
  • Document non-trivial enumerable logic for maintainability.

Syntax Table

Serial No Method Syntax/Example Description
1 map `collection.map { item code }` Transforms each element and returns a new collection.
2 select `collection.select { item condition }` Returns elements that match the condition.
3 reject `collection.reject { item condition }` Returns elements that do not match the condition.
4 reduce (or inject) `collection.reduce(initial) { memo, item code }` Combines all elements into a single value.
5 any? `collection.any? { item condition }` Returns true if any element matches the condition.
6 all? `collection.all? { item condition }` Returns true if all elements match the condition.
7 none? `collection.none? { item condition }` Returns true if no elements match the condition.

Syntax Explanation

1. map

What is map?

The map method transforms each element in a collection and returns a new collection.

Syntax

collection.map { |item| code }

Detailed Explanation

  • Applies the block to each element of the collection.
  • Returns a new collection with transformed elements.
  • Non-destructive: does not modify the original collection.

Example

numbers = [1, 2, 3]

squares = numbers.map { |n| n ** 2 }

puts squares

Example Explanation

  • Transforms [1, 2, 3] into [1, 4, 9] by squaring each number.

2. select

What is select?

The select method returns elements that match a specified condition.

Syntax

collection.select { |item| condition }

Detailed Explanation

  • Filters elements based on the block’s condition.
  • Returns a new collection containing only matching elements.

Example

numbers = [1, 2, 3, 4, 5]

even_numbers = numbers.select { |n| n.even? }

puts even_numbers

Example Explanation

  • Filters [1, 2, 3, 4, 5] to include only even numbers, resulting in [2, 4].

3. reject

What is reject?

The reject method returns elements that do not match a specified condition.

Syntax

collection.reject { |item| condition }

Detailed Explanation

  • Filters out elements based on the block’s condition.
  • Returns a new collection without the rejected elements.

Example

numbers = [1, 2, 3, 4, 5]

odd_numbers = numbers.reject { |n| n.even? }

puts odd_numbers

Example Explanation

  • Filters [1, 2, 3, 4, 5] to exclude even numbers, resulting in [1, 3, 5].

4. reduce (or inject)

What is reduce?

The reduce method combines all elements in a collection into a single value.

Syntax

collection.reduce(initial) { |memo, item| code }

Detailed Explanation

  • Takes an initial value and applies the block to combine elements iteratively.
  • Returns the final combined value.

Example

numbers = [1, 2, 3, 4]

sum = numbers.reduce(0) { |sum, n| sum + n }

puts sum

Example Explanation

  • Combines [1, 2, 3, 4] to calculate the sum, resulting in 10.

5. Custom Enumerables

How to Create Custom Enumerables?

Include the Enumerable module in a class and define the each method.

Syntax

class CustomCollection

  include Enumerable

 

  def initialize(items)

    @items = items

  end

 

  def each(&block)

    @items.each(&block)

  end

end

 

collection = CustomCollection.new([1, 2, 3])

puts collection.map { |n| n ** 2 }

Example Explanation

  • Defines a custom collection that includes Enumerable and implements each.
  • Allows the use of enumerable methods like map on the custom collection.

Real-Life Project

Project Name: Filtered Product List

Project Goal

Create a program to filter and process a list of products using enumerable methods.

Code for This Project

products = [

  { name: "Laptop", price: 1000 },

  { name: "Mouse", price: 50 },

  { name: "Keyboard", price: 70 },

  { name: "Monitor", price: 200 }

]

# Filter products under $100

affordable = products.select { |product| product[:price] < 100 }


# Map to product names

names = affordable.map { |product| product[:name] }

puts "Affordable products: \#{names.join(", ")}"

Steps

  1. Define a list of products as an array of hashes.
  2. Use select to filter products based on price.
  3. Use map to extract product names from the filtered list.
  4. Display the filtered product names.

Expected Output

Affordable products: Mouse, Keyboard

Project Explanation

  • Demonstrates filtering and transforming data using enumerable methods.
  • Highlights the expressiveness and power of Ruby enumerables.

Insights

Ruby enumerables provide a robust set of tools for working with collections. Understanding their usage enables developers to write concise, expressive, and maintainable code.

Key Takeaways

  • Use map, select, and reject for common collection transformations and filters.
  • Leverage reduce for combining elements into a single value.
  • Create custom enumerables by including the Enumerable module and defining each.
  • Write clear and expressive enumerable logic for improved readability and maintainability.