Enumerable#filter_map
This was the tip of the week in the Feb 25, 2021 Ruby Weekly Newsletter.
Enumerable#filter_map
does exactly what its name implies: it filters on certain values and then maps over those values. Let’s look at an example of what we might have written before Ruby 2.7 introduced Enumerable#filter_map.
In this example, we have an array of a few consecutive integers, and would like to calculate the squares of only the even integers:
[1,2,3,4,5,6].select { |i| i.even? }.map { |i| i ** 2 }
=> [4,16,36]
Enumerable#filter_map
does both of these commands together for us! The block we need to pass to Enumerable#filter_map
is a little different than the above two blocks. Enumerable#filter_map
will return any non-nil results of executing a block.
It is straightforward to understand the syntax of Enumerable#filter_map
if we instead think of it as doing the equivalent Enumerable#map
and then Enumberable#compact
operation. Let’s take a look at how we might obtain the same output as above with a map
and compact
:
[1,2,3,4,5,6].map { |x| x ** 2 if x.even? }.compact
=> [4,16,36]
We can use the exact same block as the map
and compact
with our new method, Enumberable#filter_map
:
[1,2,3,4,5,6].filter_map { |x| x ** 2 if x.even? }
=> [4,16,36]
Alas, Enumerable#filter_map
has turned two method calls into one! It is slick, and slightly easier than writing a select
and map
, or a map
and compact
.