When and How to Use .select .filter .find_all vs .map & .collect in Ruby

Kevin Botero
The Startup
Published in
4 min readNov 10, 2020

If you’re learning Ruby, you’ve come across some helpful tools to help write your logic called Enumerable’s. What’s an Enumerable? Basically Ruby’s special toolbox filled with a bunch of methods for traversal, searching and sorting through array’s or hashes. You can liken Ruby’s toolbox to any regular toolbox with a flathead & phillips screwdriver, a hammer, a saw, etc.

Let’s say you need to put a screw in the wall to hang a painting. What tool in your toolbox will you use?

First, you’ll need to decide what kind of screw is going in the wall. After looking at the screw, it looks like you got one with a phillips head top. Okay, great. Let’s go with the phillips head screwdriver to screw that in the wall. And as expected, went in easy. Job complete.

But wait, what if you didn’t know that the pattern on the screw was a phillips head, and you decided to use the hammer instead? Give it a few knocks on the wall, and quite a few more, and looks like the screw went right in. That took a bit more effort but we made it work.

Now, what if we went with the flathead screwdriver instead? Giving that a try it seems to catch on the pattern a bit, although it slips and you need to give it several more turns than normal just to finally get it in the wall. But hey, it worked eventually.

Based on those scenarios we can agree that there is a best way to do something, and the not so best way. Although all these tools might work for the outcome, why make the work harder and longer for no reason at all? Let’s just make sure we use the right tool each time. In comes Ruby Enumurables…

Let’s get technical

Thanks to Ruby, we get a toolbox as clear as an IKEA manual (take that as you wish). As a budding programmer, be sure to look over and be VERY familiar with these Enumerables since you’ll want to make sure you know what tools you have available to apply to your logic.

You’ll quickly realize that a handful of enumerables will keep showing up in your lines of code. Therefore, knowing how to use these and understand what’s really going on under the hood when applying them is crucial.

.select / .filter / .find_all

These are basically identical, therefore interchangeable. This is what you’ll use to iterate over an array or hash but only need the elements that return true.

Let’s say we had an array of hashes with animals, and you wanted to retrieve information for all that matched the species “dog”. We don’t want to return “turtle” or any other species.

animals = [{name: "Flower", species: "turtle", sound: "gurgles"},{name: "Riley", species: "dog", sound: "ruff"}]
animals.select { |animal| animal[:species] == "dog" }=> [{:name=>"Riley", :species=>"dog", :sound=>"ruff"},

What these .select, .filter, & .find_all enumerables actually do under the hood is go though each item in your array looking for a match that you set. In this case it’s the species “dog”. After finding a match, it will return all those matches in the form of an array.

.find

This one is self explanatory. Need to find something? .find is your friend. This will iterate and return an array. This one is very similar to.find_all, except it returns one value.

Let’s say you use .find instead of .find_all for the below data:

animals= [{name: "Flower", species: "turtle", sound: "gurgles"},{name: "Mojo", species: "cat", sound: "meow"},{name: "Cloud", species: "cat", sound: "aaaaaa"},{name: "Flower", species: "cat", sound: "meowwww"},{name: "Riley", species: "dog", sound: "ruff"},]animals.find {|ani| ani[:species] == "dog"}=> {:name=>"Riley", :species=>"dog", :sound=>"ruff"}

What this .find enumerable does under the hood is go though each item in your array looking for a match that you set. In this case it’s the species “dog”. After finding a match, it will return ONE of those matches. This is the key difference. If you need all the possible values returned for your match, then either .select or .filter or .find_all is your best tool.

.map / .collect

These are also basically identical. These iterate and return an array. If you need to perform an operation or extract information from an instance, these are your friends.

Let’s say you wanted to get only all the names of all the animals you have in your array. We don’t want to return any information besides just the names of all your animals.

animals= [{name: "Flower", species: "turtle", sound: "gurgles"},{name: "Mojo", species: "cat", sound: "meow"},{name: "Cloud", species: "cat", sound: "aaaaaa"},{name: "Flower", species: "cat", sound: "meowwww"},{name: "Riley", species: "dog", sound: "ruff"},]
animals.map { |animal| animal[:name] }=> ["Flower", "Mojo", "Cloud", "Flower", "Riley"]

What these .map & .collect enumerables actually do under the hood is go though each item in your array and pull the information you specified, and puts them in an array. In this case it’s “name”. After going through each item in your array, it will extract the value for “name” and return all those in the form of an array.

--

--

Kevin Botero
The Startup

I get techy on here. { firstName: “Kevin”, lastName: “Botero”, interests: [“tech”, “startups”] }