Andrew Lewell
Posted on November 10, 2019
Ruby's Enumerable module is a collection of built-in methods that are used to iterate over collections of data. These powerful methods allow the user to manipulate arrays and hashes. Below is a brief look at some of the more commonly used Enumerables I have come across during my journey learning to code.
What are arrays and hashes?
Before we dive into the Enumerables themselves, let's quickly recap on arrays and hashes.
An array is a data structure consisting of a collection of elements, each identified by an index. Due to this index, an array can be considered an ordered list. In Ruby, arrays are denoted with square brackets. Indexes start at 0, so the first element would be index 0, second would be index 1, third would be index 2, etc.
colours = ["red", "green", "blue"]
A hash is a data structure consisting of a collection of keys and their corresponding value. Together, they are called a key value pair. They are similar to arrays, but have a key instead of a hidden integer index.
british_weather = {temperature: "cold", rainfall: "lots"}
It is possible to nest both arrays inside hashes, and hashes inside arrays. This allows Ruby developers to map out almost any data set imaginable.
.each
The .each
method is used to iterate over elements in an array, or key value pairs in a hash.
colours = ["red", "green", "blue"]
colours.each do |colour|
puts "This is #{colour}!"
end
#=> "This is red!"
#=> "This is green!"
#=> "This is blue!"
The .each
method (and many of the other Enumerable methods) takes in two arguments: an element and a block. The element is inside the pipes, and is used to indicate the individual element being used within the block in the current iteration.
The block is everything within the do
and end
and this code is run on each element in the array. In this case, puts "This is #{colour}!"
is being run on each element of the colours array.
Note: it is possible to replace do
and end
with {
and }
to keep the code on one line. Using the .each
method with a hash is the same syntax, except both the key and value are part of the element argument.
colours.each do { |colour| puts "This is #{colour}" }
hash.each do { |key, value| block }
The .each
method is non-destructive, meaning it will leave the original array/hash unchanged. But what if we need to modify the original array or hash?
.map
The .map
method behaves in a similar way to .each
, except that the original array is mutated based on the code within the block.
colours = ["red", "green", "blue"]
colours.map { |colour| colour.capitalize }
#=> ["Red", "Green", "Blue"]
In this example, the capitalize method is being used on each element of the array, mutating the original colours
array.
.reduce
The .reduce
method will combine all elements of an array or hash into a single value, based on a given block or a symbol operator.
costs = [5, 5, 10, 2, 1]
costs.reduce(:+)
#=> 23
The :+
symbol operator here will add each element together, resulting in a total value. There are many different uses for .reduce
depending on the operator or code block passed in.
.select
The .select
method returns a new array with all elements from an array that return true for a given block.
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nums.select { |num| num > 5 }
#=> [6, 7, 8, 9, 10]
The .select
method iterates over all numbers in the nums
array, and checks if the number is greater than 5. All elements that satisfy this logic are placed into a new array.
The .find
method behaves in a similar way, but returns the first element that satisfies the block, instead of an array of all elements that do.
.max_by/.min_by
These methods will select from an array or hash the maximum or minimum element based on a given block.
animals = ["tiger", "gorilla", "rat"]
animals.max_by { |animal| animal.length }
#=> "gorilla"
animals.min_by { |animal| animal.length }
#=> "rat"
animals.max_by(2) { |animal| animal.length }
#=> ["gorilla", "tiger"]
As you can see, the .max_by
method selects the longest string because of the .length
in the block, and .min_by
selects the shortest string. There is also an optional argument to be passed in so you can select the max n or min n.
There are over 57 different Enumerables so I will not cover each of them here but please refer to the Ruby Enumerables documentation below in sources to dive deeper into these fantastic built in methods. Hopefully this post will have helped introduce you to the power of Ruby Enumerables.
Sources
https://ruby-doc.org/core-2.6.5/Enumerable.html
https://en.wikipedia.org/wiki/Array_data_structure
https://docs.ruby-lang.org/en/2.0.0/Hash.html
Posted on November 10, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.