Ruby Inject

You probably frequently have to iterate through a list and accumulate a result that changes as you iterate. Let’s take the following array:

nums = [1, 3, 5, 7]

If you want to find a sum of all the items in the array, you could write something like this:

sum = 0
nums.each { |n| sum += n }

This works fine, but it doesn’t look much elegant. Luckly, for us that wants to be elegant there is a inject method.
(See: Enumerable::inject)

sum = nums.inject(0) { |x,n| x+n }

This code does the same thing, but also looks cool. Inject acomplish this by using accumulator or accumulated value (x). At each step accumulated value is set to the value returned by the block. Here, we set accumulator initial value to 0, and at each step current value from array (n) is added to accumulated value.

If initial value is omitted, the first item is used as the accumulator initial value and is then omitted from iteration.

sum = nums.inject { |x,n| x+n }

Is same as

sum = nums[0]
nums[1..-1].each { |n| sum += n }

Another example.
We have array with five names:

names = ["michael", "ron", "scottie", "dennis", "toni"]

The following code:

string = names.inject("") { |x,n| x << "#{n} " }

Will output:

=> "michael ron scottie dennis toni "

You can get the same output with:

string = ""
names.each { |n| string << "#{n} "}

Now, let’s say you won’t to separate them with comma, and capitalize those that have more then four characters.
You can do it like this:

string = ""
names.each do |n|
  name = n.length > 4 ? n.capitalize : n
  n == names.last ? string << name : string << "#{name}, " 

Or like this:

string = names.inject("") do |x,n|
  name = n.length > 4 ? n.capitalize : n
  n == names.last ? x << name : x << "#{name}, "

In both ways we get the same result:

=> "Michael, ron, Scottie, Dennis, toni"

Technorati Tags: , , ,

9 thoughts on “Ruby Inject

  1. Doesn’t like my entity chars?
    # From:
    n == names.last ? string << name : string << “#{name}, ”
    # To:
    string << ((n==names.last) ? name : string + “,”)


  2. Great article! thanks. And if you like idioms you should check this page out gives a list of French idioms with their English translations – really shows how funny language is out of context (and what a nightmare it can be to translate languages!). 🙂


  3. Your last example would be easier to do with map and join:

    string = {|n| n.length > 4 ? n.capitalize : n }.join(“, “)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s