Iteration Reiteration
Let’s learn when and how to use the below iterators with some examples in code.
.each { |x| block } iterates over each and returns same number of elements
.map { |x| block } same as .each but with new mapped array
.select { |x| block } same as .map but only with selected elements
.find { |x| block } same as .select but with first found element
Iterators
What if I told you that you could abstract all of the details of an algorithm into one word in code? That’s the power of iterators. In short, they loop through every element of a dataset to run a command on each data element.
As developers, we aim to be as concise and precise as possible. Let’s dive into the four iterators of .each, .map, .select and .find to learn when and how to use their powerful abstractions.
Tying this into the real world, we’ll pretend that we have iteration available in a program to help us win a game of Scrabble.
Let’s play!
Here are the seven letters we pulled from the bag:
From our letters, here are the words we’ve derived in our heads.
7 Letters - drizzle
5 Letters- idler, riled
4 Letters- ride, deli, lier
3 Letters- led, eld
2 Letters- el
In our program, let’s first create an array with our words. We’ll then iterate upon this array with our program to crush our friends in this epic Scrabble game.
words = ["drizzle", "idler", "riled", "ride", "deli", "lier", "die", "ide", "el"]
For the sake of simplicity for this entire hypothetical game, let’s assume that after every turn, the replacement letters we pull from the bag are ironically the same as the letters we played in our last turn.
.each
First things first. Our memory sucks, plus why would we depend on it when we have a program?! Let’s create a variable to invoke with our .each iterator.
each = words.each { |word| word }
Now we can simply invoke each in our program to return all of our words:
=> ["drizzle", "idler", "riled", "ride", "deli", "lier", "led", "eld", "el"]
.map
Turns out that our friends are getting suspicious of us. They’re challenging that our words (yes, all of them) are proper nouns. Proper nouns are always capitalized, so to easily show them that all of our words are not proper nouns, let’s capitalize them all for display. This way, it’s easier for our friends to see clearly that they’re not proper nouns. We’ll create a map variable to invoke with our .map iterator.
map = words.map { |word| word.capitalize }
We use .map here because .each always returns our original array, whereas .map actually transforms it.
=> ["Drizzle", "Idler", "Riled", "Ride", "Deli", "Lier", "Led", "Eld", "El"]
No proper nouns here! Tell your friends to shush 🤫.
.select
It’s our turn, and we see a sweet play on the board that needs a four-letter word. Well, we can just create a select variable to invoke our .select iterator to return all of our options.
select = words.select { |word| word.length == 4 }
We use .select here because we only want to return the four-letter words.
=> ["ride", "deli", "lier"]
Although .map would transform and return each element’s evaluated result of true (==4) or false (!=4), this would not have been as helpful. We wanted to simply return the elements in their original form that were selected as true. The number of results of .map are always equal to the number of elements of its original array. The number of results of .select are only equal to the number of elements evaluated as true, which are returned in their original form.
.find
It’s our turn again. We’re running out of time because we’ve been looking at the board too long to try to find a play with a long word. There are plenty of wide-opened three-letter word plays we could do. We only have three seconds left, so we just want our program to show us the first three-letter word we have available. So, we create a find variable to invoke our .find iterator.
find = words.find { |word| word.length == 3 }
In a millisecond, our program returns our first three-letter word. Just in the nick of time!
=> "led"
We could have used .select to return all three-letter words, but that would have caused us to have to choose one of those three-letter words to play. That would have taken us more time, that we didn’t have.
Chaining Methods
Ok, it’s judgement day. We’re in second place and all we have to do to win is to play any four-letter word. However, our friends are highly suspicious that we only have proper nouns available. In extra-sportsmanship fashion, we decide to have our beloved program show them all of our four-letter words, capitalized. This will squash their qualms just as we did before, shushing them right before our final move. Let’s create a select_map variable that we can invoke our .select and .map iterators upon, for our final showdown.
select_map = words.select { |word| word.length == 4 }.map { |word| word.capitalize }
Our program returns our three options, all capitalized. No proper nouns here either! Victory is imminent.
=> ["Ride", "Deli", "Lier"]