Strategies for Looping Through Collections in Ruby (Part 3: Reduce/Inject)
So, what does one do when he’s stuck inside all day with a cold? Write a Medium blog post, of course! Though it’s only been 48hours since my last post, I figured I’d waste no time in bringing you, the reader, the (not-so) long-awaited third chapter of my three part series on looping through collections in ruby. As I wrote in my previous articles here and here, this three-part series is meant to serve as a simple summary of three(ish) enumerator class methods that I often come across when dealing with and manipulating collections (mostly arrays, but sometimes hashes and ranges) in Ruby. The three methods are #Map(or #Collect), #Select(conversely, #Reject), and #Reduce (or #Inject). These enumerator methods seem to be the most widely used when manipulating collections, and are thus important in any fundamental understanding of Ruby. Broadly speaking, the #Map function manipulates elements of a collection based on given block parameters; the #Select function “filters” a collection based on block parameters, and returns a new array based on these filters; the #Reduce method returns a new value that combines elements of a collection based on block parameters. And just to be clear, when I say “block parameters”, I mean this:
{|item| block }Where the "item" refers to each element of the collection, and the "block" is the what is actually "being done" to each element in the array
This post is about the #reduce and #inject methods. I will give some examples of how these methods can be used, but first, let’s start off with some arrays to manipulate (you know the drill by now):

For starters, I will say this: of the three blog posts I’ve done on manipulating collections, the Ruby documentation on #reduce/inject seems to be especially convoluted. As any good Rubyist knows, the beautiful (or frustrating) feature of the language is its use of multiple forms of syntax/interchangeable public instance methods that are used to complete identical tasks. I will do my best here to explain how I, as a total coding noob, understand the general nuances of the syntax. The best thing a beginner programmer can dow when learning a new method/function/syntax is to open up Sublime and simply begin playing around with the examples given on the official documentation pages for each language. Got it? Alrighty, let’s begin.

This is the “shorthand” syntax for reduce/inject that doesn’t take a block argument. I’d say that this syntax is pretty straightforward; in all four of these examples, the #reduce/inject method takes two arguments (the first of which is optional), and returns the combined elements of the collection (an array, in this case) based on the operation in the second argument. The first argument is the initial, which, as you can probably guess, is the initial element that is “pushed” into the array that is being manipulated; in other words, the array number_array is [1, 5, 7, 12], but when an initial argument is specified (in my examples, it is 2 or 3), then that number is “pushed” to the beginning of the number_array, which essentially creates a copy that would look like [initial, 1, 5, 7, 12]. Pretty straightforward, right? Now let’s look at a different syntax that this time takes a block argument:

As we can see here, this is simply a “longhand” version of the previous syntax. The second function here contains an initial of 3. The Ruby documentation uses |memo| as the initial block element, which is an abbreviation for “memory”. In these cases, |memo| could also be written as “sum” or “product”, respectively, because that’s essentially what it represents: the “tally” of all the elements in the array being manipulated. For a more clear understanding of |memo|, let’s take a look at an array of strings below (this example is borrowed heavily from Ruby’s official documentation website):

There’s a lot going on here, I know. I’ll do my best to break this down step by step, but hopefully our understanding of |memo| will start to clarify exactly what’s going on here. Let’s start from the top:
shortest = %w{cat sheep superduper bear}
is simply a fancy way of writing
shortest = [“cat”, “sheep”, “superduper”, “bear”]
Got it? Alright. Now let’s walk through what happens in each iteration through the array (and hopefully my understanding is correct here). The |memo| block, as I alluded to above, is basically a memory “storage” that “saves” the value of each element in the array as the function runs its loop. Looking at the longest function, we can see what is happening. The first loop through the array stores “cat” in the |memo| block element, and compares it, in this case, to “cat”, which is also the |word| block element. The logic then asks: is “cat” longer than “cat”? In this case, it is not; thus, if the loop were to end right here, “cat” as the block element |word| would be printed to the console. The next loop through the array will ask: is “cat” (now stored as the |memo| block element) longer than “sheep”(the |word| block element)? It is not, and so this iteration will “override” the previous comparison; “sheep” is, so far, the longest word in the array. The next iteration will ask, is “sheep” (now stored as the |memo| block element) longer than “superduper”(now the |word| block element)? Again, it is not, meaning “superduper”will be returned as the word block element.
Just remember that the ternary operator syntax:
memo.length > word.length ? memo : word
is read as:
if memo.length > word.length then return memo else return word
So here’s what’s happening on each loop:
cat.length > cat.length? No, so return “cat”(word)
cat.length > sheep.length? No, so return “sheep”(word)
sheep.length > superduper.length? No, so return “superduper”(word)
superduper.length > bear.length? YES! So return “superduper”(memo)
Voila! Pretty straightforward when broken down like this, yeah? Finally, as a form of good practice, here is how you write a #reduce/inject function without using those methods:

And that’s a wrap, folks. Thank you for tuning in to this three part series. So what’s next? I’m planning on writing a nice, long article on the differences in Scope between Ruby and Javascript. Stay tuned!
