Summing the Items of an Array
Problem
You want to add together many objects in an array.
Solution
There are two good ways to accomplish this in Ruby. Plain vanilla iteration is a simple way to approach the problem:
collection = [1, 2, 3, 4, 5] sum = 0 collection.each {|i| sum += i} sum # => 15
However this is such a common action that Ruby has a special iterator method called inject, which saves a little code:
collection = [1, 2, 3, 4, 5] collection. inject(0) {|sum, i| sum + i} # => 15
Discussion
Notice that in the inject solution, we didn't need to define the variable total variable outside the scope of iteration. Instead, its scope moved into the iteration. In the example above, the initial value for total is the first argument to inject. We changed the += to + because the block given to inject is evaluated on each value of the collection, and the total variable is set to its output every time.
You can think of the inject example as equivalent to the following code:
collection = [1, 2, 3, 4, 5] sum = 0 sum = sum + 1 sum = sum + 2 sum = sum + 3 sum = sum + 4 sum = sum + 5
Although inject is the preferred way of summing over a collection, inject is generally a few times slower than each. The speed difference does not grow exponentially, so you don't need to always be worrying about it as you write code. But after the fact, it's a good idea to look for inject calls in crucial spots that you can change to use faster iteration methods like each.
Nothing stops you from using other kinds of operators in your inject code blocks. For example, you could multiply:
collection = [1, 2, 3, 4, 5] collection.inject(1) {|total, i| total * i} # => 120
Many of the other recipes in this book use inject to build data structures or run calculations on them.
See Also
- Recipe 2.8, "Finding Mean, Median, and Mode"
- Recipe 4.12, "Building Up a Hash Using Injection"
- Recipe 5.12, "Building a Histogram"