Megan
Posted on November 12, 2019
Before starting Flatiron School, I was obsessed with using .each. It was one of the first ruby enumerable methods that I was taught and I found it to be such a security blanket. It was always there for me: simple to understand, usually returning a functioning output, easy to go to in a bind, just my favorite enumerable method that I could always depend on.
But having been just a little over one week at Flatiron School, I was being reminded daily in every lab and by teachers and coaches to steer away from .each in almost every instance and method. At first I really couldn't understand what all the hype was about. Sure, it is general... and well yeah it doesn't get you to exactly the information you want without needing another line or two of code... but it usually returns something close to what you're looking for or at least gets you on the path there!
Or so I thought.
As I began slowly discovering and using these other enumerable methods more: .map, .select, .inject, .max, and the like, I realized I had been wasting a lot of time and precious code. With my blanket ripped from my hands, I was able to see how I'd been clinging to .each for dear life, returning the same values when I could have been modifying my data and returning it all in one step!
These other methods, though requiring a bit more research and understanding to use, are able to simplify code and return more succinct results than my plain old .each. As I reviewed the enumerables documentation, I realized all of the other ruby enumerable methods are built off of .each. So logically .each was just a stepping stone that would always require another step to get to the desired result. In fact, often times, it was a long winded route to even getting close to what I wanted. When the information I needed could be returned right away all along.
Brimming with excitement about my newfound knowledge, I thought it'd be super cool to share a few of my more commonly used enumerable methods with all of you. So maybe they can change your mind about .each like they did for me, or at least give you a few helpful methods to get you to your results a little quicker.
.map
.map is one of my favorites because it is very universal and can return different types of results. It iterates over an array, range, or hash and always returns an array of changed values that satisfy the given condition in the block (part in the curly braces{}). It, however, does not change the original array.
Given an operation statement, an array of changed values will be returned.
But given a conditional statement, .map will return an array of boolean values.
This can be very helpful if true/false values were what you were looking for, however, that isn't always the case. So that is just something to be aware of in those cases.
But when you need an array with all of your original values changed, .map is there for you.
.select
.select is a bit less picky than .map and a little more forgiving when operational or conditional statements are pushed in the block. Your result will always be an array of new values as well, but these values are only the ones that satisfied the statement and return true. This method also does not change the original array.
I find because of this that .select is often times associated with our friend ==. This isn't always the case, but it's usually a good reminder if you see one then you might need the other.
.inject / .reduce
.inject and .reduce are used interchangeably and can be very time saving when implemented correctly. They both accept arrays of integers, strings, etc. and combine them together using mathematical operations. The convenient part is that you don't need a separate total or starting point as that is built into the method.
In the case below, we want a sum of the values in our array. Both methods conveniently hold our starting sum or, in the example total, to which we will just add each value in the array to as we iterate over it. It will return just the sum in the end.
I have found these methods to be very useful for many types of problems, but especially ones in which a total is to be calculated or kept track of.
.max / .min
Last, but not least!, we have .max and .min. I put them together because they serve the same purpose but in the opposite capacity. When you need the first item in an array, you would go for .min, but if you need the last item in an array, you want .max. I am especially fond of these methods because when implemented with a spaceship (<=>) they can be used to make comparisons as well. I find this to be a great alternative to .sort and can sometimes be a shortcut straight to your result.
They can both even be used with an integer argument to get more than one value returned in the results array.
And these were just the tip of the iceberg! There are so many more enumerable methods for ruby that are worth looking into as they can change your data in fantastic ways and really simplify your code.
After all of this I couldn't help but think well... .each can't be all bad. And it's not! It is actually very useful but in the right situations. I understand now that .each has gotten a bad rep because, when used inappropriately, it can be clunky and make your code un-DRY. But it is still a very important method that can be very useful for processing over data and returning your results unchanged. When you only need to iterate over your data and you don't need to collect any new results, .each is great. But when data is to be change and returned, sometimes there might be a more specific, concise enumerable method that could be implemented that saves time and code.
I think the most important part of all of this is knowing the time and place for using these methods. And .each will always have a place in my heart, but I've learned to open up that space to these other amazing enumerable methods that are equally worthy of some love.
Posted on November 12, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.