This tutorial provides a comprehensive guide to working with Ruby collections, including arrays, hashes, and enumerable methods like `map`, `select`, `reduce`, and `each_with_index`. You’ll learn how to manipulate data, solve real-world problems, and write efficient Ruby code.
Step 1: Understanding Arrays and Basic Operations
Arrays are ordered collections of objects. They are versatile and commonly used in Ruby. Learn how to create, access, and modify arrays.
- Creating Arrays: Use [] or Array.new.
- Accessing Elements: Use indices (e.g., array[0]).
- Modifying Arrays: Add (<< or push), remove (pop or delete), and update elements.
# Create an array
fruits = ['apple', 'banana', 'cherry']
# Access elements
puts fruits[0] # Output: apple
# Modify array
fruits << 'orange'
fruits.delete('banana')
puts fruits # Output: ['apple', 'cherry', 'orange']Practice Exercise
Create an array of your favorite books. Add a new book, remove the first book, and update the second book to a different title. Print the final array.
Show Solution
books = ['1984', 'To Kill a Mockingbird', 'The Great Gatsby']
books << 'Brave New World'
books.delete_at(0)
books[1] = 'Pride and Prejudice'
puts books # Output: ['Pride and Prejudice', 'The Great Gatsby', 'Brave New World']Step 2: Working with Hashes
Hashes are collections of key-value pairs. They are ideal for storing and retrieving data by unique keys.
- Creating Hashes: Use {} or Hash.new.
- Accessing Values: Use keys (e.g., hash[:key]).
- Modifying Hashes: Add, update, or delete key-value pairs.
# Create a hash
person = { name: 'Alice', age: 30, city: 'New York' }
# Access values
puts person[:name] # Output: Alice
# Modify hash
person[:age] = 31
person[:job] = 'Engineer'
person.delete(:city)
puts person # Output: { name: 'Alice', age: 31, job: 'Engineer' }Practice Exercise
Create a hash representing a product with keys like name, price, and quantity. Update the price, add a new key discount, and remove the quantity key. Print the final hash.
Show Solution
product = { name: 'Laptop', price: 1200, quantity: 5 }
product[:price] = 1100
product[:discount] = 0.1
product.delete(:quantity)
puts product # Output: { name: 'Laptop', price: 1100, discount: 0.1 }Step 3: Using `each` for Iteration
The each method iterates over each element in a collection. It is a fundamental way to process arrays and hashes.
- Array Iteration: Pass a block to each.
- Hash Iteration: Iterate over keys and values.
# Iterate over an array
fruits = ['apple', 'banana', 'cherry']
fruits.each { |fruit| puts fruit }
# Iterate over a hash
person = { name: 'Alice', age: 30 }
person.each { |key, value| puts "#{key}: #{value}" }Practice Exercise
Given an array of numbers, print each number multiplied by 2. For a hash of student grades, print each student's name and their grade.
Show Solution
numbers = [1, 2, 3, 4]
numbers.each { |num| puts num * 2 }
grades = { 'Alice' => 90, 'Bob' => 85 }
grades.each { |name, grade| puts "#{name}: #{grade}" }Step 4: Transforming Data with `map`
The map method transforms each element in a collection and returns a new array. It is useful for data transformation tasks.
- Array Transformation: Apply a block to each element.
- Hash Transformation: Convert hashes into arrays or other structures.
# Transform an array
numbers = [1, 2, 3]
squares = numbers.map { |num| num ** 2 }
puts squares # Output: [1, 4, 9]
# Transform a hash
person = { name: 'Alice', age: 30 }
details = person.map { |key, value| "#{key}: #{value}" }
puts details # Output: ['name: Alice', 'age: 30']Practice Exercise
Given an array of temperatures in Celsius, convert them to Fahrenheit using map. For a hash of product prices, create a new array with prices increased by 10%.
Show Solution
celsius = [0, 10, 20, 30]
fahrenheit = celsius.map { |temp| (temp * 9 / 5) + 32 }
puts fahrenheit # Output: [32, 50, 68, 86]
prices = { 'apple' => 1.0, 'banana' => 0.5 }
increased_prices = prices.map { |item, price| [item, price * 1.1] }.to_h
puts increased_prices # Output: { 'apple' => 1.1, 'banana' => 0.55 }Step 5: Filtering Data with `select`
The select method filters elements based on a condition. It returns a new collection containing only the elements that satisfy the condition.
- Array Filtering: Use a block to define the condition.
- Hash Filtering: Filter key-value pairs based on criteria.
# Filter an array
numbers = [1, 2, 3, 4, 5]
even_numbers = numbers.select { |num| num.even? }
puts even_numbers # Output: [2, 4]
# Filter a hash
person = { name: 'Alice', age: 30, job: 'Engineer' }
filtered = person.select { |key, value| value.is_a?(String) }
puts filtered # Output: { name: 'Alice', job: 'Engineer' }Practice Exercise
Given an array of numbers, filter out all numbers greater than 10. For a hash of employee data, filter out employees under the age of 25.
Show Solution
numbers = [5, 15, 20, 25]
filtered_numbers = numbers.select { |num| num 30, 'Bob' => 22, 'Charlie' => 28 }
filtered_employees = employees.select { |name, age| age >= 25 }
puts filtered_employees # Output: { 'Alice' => 30, 'Charlie' => 28 }Step 6: Aggregating Data with `reduce`
The reduce method combines all elements in a collection into a single value. It is ideal for tasks like summing numbers or finding maximum values.
- Array Aggregation: Use a block to define the operation.
- Hash Aggregation: Combine values based on keys.
# Sum an array
numbers = [1, 2, 3, 4]
sum = numbers.reduce(0) { |total, num| total + num }
puts sum # Output: 10
# Combine hash values
prices = { apple: 1.0, banana: 0.5, cherry: 2.0 }
total_cost = prices.reduce(0) { |sum, (item, price)| sum + price }
puts total_cost # Output: 3.5Practice Exercise
Given an array of numbers, calculate the product of all elements. For a hash of sales data, calculate the total revenue.
Show Solution
numbers = [2, 3, 4]
product = numbers.reduce(1) { |total, num| total * num }
puts product # Output: 24
sales = { 'apple' => 100, 'banana' => 200, 'cherry' => 150 }
total_revenue = sales.reduce(0) { |sum, (item, revenue)| sum + revenue }
puts total_revenue # Output: 450Step 7: Using `each_with_index` for Indexed Iteration
The each_with_index method iterates over a collection while providing access to both the element and its index. It is useful for tasks requiring index-based logic.
- Array Iteration: Access both element and index.
- Hash Iteration: Access key, value, and index.
# Iterate with index
fruits = ['apple', 'banana', 'cherry']
fruits.each_with_index do |fruit, index|
puts "#{index}: #{fruit}"
end
# Output:
# 0: apple
# 1: banana
# 2: cherryPractice Exercise
Given an array of names, print each name with its position (starting from 1). For a hash of product ratings, print each product with its rank (based on index).
Show Solution
names = ['Alice', 'Bob', 'Charlie']
names.each_with_index do |name, index|
puts "#{index + 1}: #{name}"
end
# Output:
# 1: Alice
# 2: Bob
# 3: Charlie
ratings = { 'apple' => 4.5, 'banana' => 3.8, 'cherry' => 4.0 }
ratings.each_with_index do |(product, rating), index|
puts "#{index + 1}: #{product} (Rating: #{rating})"
end
# Output:
# 1: apple (Rating: 4.5)
# 2: banana (Rating: 3.8)
# 3: cherry (Rating: 4.0)Step 8: Combining Enumerable Methods
Enumerable methods can be chained to perform complex operations in a concise manner. This step demonstrates how to combine methods like map, select, and reduce.
# Example: Filter even numbers, square them, and sum the results
numbers = [1, 2, 3, 4, 5]
result = numbers.select { |num| num.even? }
.map { |num| num ** 2 }
.reduce(0, :+)
puts result # Output: 20Practice Exercise
Given an array of words, filter out words shorter than 4 characters, capitalize the remaining words, and join them into a single string.
Show Solution
words = ['ruby', 'is', 'awesome', 'and', 'fun']
result = words.select { |word| word.length >= 4 }
.map { |word| word.capitalize }
.join(' ')
puts result # Output: 'Ruby Awesome Fun'Sign in to take Cornell notes on this lesson — they save automatically and stay with your account.