Understanding the Basics of Enumerable#inject

Enumerable#inject

While trying to complete what seemed like very simple task, I stumbled across Enumerable#inject. The task was to take an array of numbers and calculate the sum of all of the numbers. The beginner programmer in me said, "Hey, lets iterate through the numbers using the handy dandy Enumberable#each and just add the numbers together." The example looks something like this:

numbers = [1, 2, 3, 4, 5]   
numbers.each { |num| num + num }

Not only does this code not give me the sum of all of the numbers, the return value of #each is the original array. If I were to print out what is happening in this method it would look something like this:

1+1 = 2 
2+2 = 4
3+3 = 6
4+4 = 8
5+5 = 10
=> [1, 2, 3, 4, 5]

This solution does not work because the result of the code block is not being stored anywhere. So, as it stands, there is no way to keep track of the 'sum' of all the numbers.

In comes #Inject

Solving this problem with Enumerable#inject looks like this:

numbers.inject { |result, num| result + num } 
=> 15

confused

Breakdown

On its surface #inject looked very confusing to me. Why are there two arguments being passed in the block if we are operating on a one-dimensional array? How exactly is it working? Something that looks very simple is doing a lot of cool work for us. Lets break it down step by step.

Step 1

numbers.inject { |result, num| result + num }

In this case numbers is set to our array of numbers 1-5. Our initial value is set to the argument result inside of our block. This will be used to store the return value of each iteration. We could have passed in an argument to our inject method by doing this:

numbers.inject(0) 

In which result, or our initial value would have been 0. However, this is optional and when an argument is not passed in the initial value will be the first element in the array.

Step 2

This method is going to iterate over every element in the array once, temporarily storing the return value in the result argument. The first iteration would look something like this:

[1, 2, 3, 4, 5].inject { |result, num| result + num } 
      result = 1 & num = 2 
      result + num = 3
      result = 3 

Step 3

We know now that the result argument is temporarily set to 3. In the next iteration, it is going to take that result and add it to the next element in the array which is 3.

result = 3 & num = 3 
result + num = 6
result = 6

Step 4

This process will continue until every element of the Array has been iterated over. The last step of the iteration will look something like this:

result = 10 & num = 5
result + num = 15
result = 15

Once the code has been executed for every element in the array, the return value is going to be our result, which is 15.

han solo

Is that it?

Not quite, but we now have a pretty basic understanding and can continue to build off of this knowledge. Albeit a very simple calculation and example, #inject is a very powerful tool to use in Ruby. This example is simply designed to provide you and myself with a brief understanding of what #inject is doing and why it is useful in this scenario.

Additional Sources

Feel free to check out some more of the following sources to get a more in-depth understanding of this Enumerable:
Jay Fields on Enumerable#inject

Ruby Documentation

The Bastards Book of Ruby

Show Comments
comments powered by Disqus