Introduction
Enumerable
. Debatably one of, if not the, most powerful features in Ruby. As a majority of your time in programming is dealing with collections of items it's no surprise how frequently you'll see it used.
Difficulty
Foundational
Some knowledge required of functions in Ruby. This post focuses on foundational and fundamental knowledge for Ruby programmers.
Prerequisite Reading:
- Understanding Ruby - Blocks, Procs, and Lambdas
- Understanding Ruby - to_proc and Function Interfaces
- Understanding Ruby - Triple Equals
- Understanding Ruby - Comparable
Enumerable
Enumerable
is an interface module that contains several methods for working with collections. Many Ruby classes implement the Enumerable
interface that look like collections. Chances are if it has an each
method it supports Enumerable
, and because of that it's quite ubiquitous in Ruby.
Note: This idea was partially inspired by Lamar Burdette's recent work on Ruby documentation, but takes its own direction.
Sorting
Perhaps you're the sort that likes everything to be in a certain order, but how are you going to sort it? Will it be by default, length, or what? Ruby gives you a lot of power to figure all of that out.
All of these methods require that the underlying class implements <=>
, or you will see errors.
#sort
sort
will sort collections:
[4, 2, 1].sort
# => [1, 2, 4]
Remembering back to Comparable
it can also take a Block Function with a comparator Rocketship Operator (<=>
):
[1, 2, 4].sort { |a, b| b <=> a }
# => [4, 2, 1]
It follows the same rules of deciding precedence by the return of the comparator, and that has to be an Integer
of one of -1, 0, 1
in value.
#sort_by
sort_by
is interesting in that it implements the comparator behind the scenes and uses a single attribute instead:
%w(a fresh lively lemur jumps over a tea kettle).sort_by(&:length)
# => ["a", "a", "tea", "over", "jumps", "fresh", "lemur", "lively", "kettle"]
The docs do note that this is much slower, because nothing nice ever comes for free, and why knowing what Comparable
is is quite useful to define how sort
behaves by default.
Comparing
All of these methods require that the underlying class implements <=>
, or you will see errors.
#max
max
gets the item with the maximum value in a collection:
[1, 2, 3].max
# => 3
When provided a Block Function it works much like sort
and its comparator:
[1, 2, 3].max { |a, b| b <=> a }
# => 1
Though if you want to do something like that it probably makes more sense to use min
.
It can also take a number to get multiple max numbers:
[1, 2, 3, 4, 5].max(3)
# => [5, 4, 3]
Those numbers will be in order of maximum to least so, and this can also take a Block Function the same as above.
#max_by
max_by
is very much like sort_by
except in that it will give the maximum elements rather than sorting:
%w(a fresh lively lemur jumps over a tea kettle).max_by(&:length)
# => "lively"
This can also take a number:
%w(a fresh lively lemur jumps over a tea kettle).max_by(2, &:length)
# => => ["kettle", "lively"]
sort
mentions this, but elements that are both 0
when compared may come back in unexpected order, but in this case the order that they were found in reverse.
#min
min
is the inverse of max
, and works much the same way:
[1, 2, 3].min
# => 1
See max
for accepting a number and a Block Function
#min_by
The same can be said of min_by
versus max_by
:
%w(a fresh lively lemur jumps over a tea kettle).min_by(&:length)
# => "a"
See max_by
for more options.
#minmax
minmax
, however, is a bit different. It returns both the minimum and maximum element in a list as a pair:
[1, 2, 3, 4, 5].minmax
# => [1, 5]
As with the min
methods these behave the same.
#minmax_by
minmax_by
follows the same conventions as well:
%w(a fresh lively lemur jumps over a tea kettle).minmax_by(&:length)
# => ["a", "lively"]
See max_by
for more options.
Wrapping Up
The next few articles will be getting into the various parts of Enumerable
, grouped by functionality:
TransformingPredicate ConditionsSearching and FilteringSorting and Comparing- Counting
- Grouping
- Combining
- Iterating and Taking
- Coercion
While lazy
is part of Enumerable
that deserves a post all its own, and we'll be getting to that one soon too.
Want to keep up to date on what I'm writing and working on? Take a look at my new newsletter: The Lapidary Lemur
Top comments (0)