Ruby’s inject method

Ruby’s inject method can be used to build or reduce arrays and hashes. Suppose we have two arrays and would like to combine them in a hash.

# given arrays
a = [:uno, :dos, :tres]
b = ["one", "two", "three"]
# desired hash
{:uno=>"one", :dos=>"two", :tres=>"three"}

The inject method can be used to construct the hash, but the syntax is a bit confusing:

a.inject({}) {|memo, numero|  memo[numero] = b[a.index(numero)]; memo}
# more readable syntax
a.inject({}) do |memo, numero|
  memo[numero] = b[a.index(numero)]
  memo
end

A more concise and readable solution is available with the zip() method.

a.zip(b).inject({}) { |memo, (numero, number)| memo[numero] = number; memo }
# or you can cheat and use Hash đŸ™‚
Hash[a.zip(b)]

The inject method is passed an empty hash as a starting point and the memo (common term for the accumulator in inject, but you can call it anything) keeps track of the hash as it is updated every iteration. By printing memo every iteration, it is easier to see the purpose of the accumulator:

>> a.inject({}) {|memo, numero|  memo[numero] = b[a.index(numero)]; p memo}
{:uno=>"one"}
{:uno=>"one", :dos=>"two"}
{:uno=>"one", :dos=>"two", :tres=>"three"}
=> {:uno=>"one", :dos=>"two", :tres=>"three"}

Jay Fields has a nice example of using inject to convert [1, 2, 3, 4, 5, 6] to [‘2’, ‘4’, ‘6’] (an array that only includes the even elements and converts them to strings) using inject.

[1, 2, 3, 4, 5, 6].inject([]) { |memo, num| memo << num.to_s if num % 2 == 0; memo }

IF we don’t use inject, we need to chain select() and map(), which is not as nice:

[1, 2, 3, 4, 5, 6].select {|num| num if num % 2 == 0}.map(&:to_s)

Inject is also good at reducing arrays. Use inject to sum the values in the following array [1, 2, 3, 4].

[1, 2, 3, 4].inject{|memo, num| memo += num; memo}

Inject can be used when you instantiate an empty array or hash and then populate it with iteration, so be on the lookout and try to use it in your projects!

Advertisements

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s