Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need a simple explanation of the inject method

Tags:

syntax

ruby

People also ask

What is inject function?

In mathematics, an injective function (also known as injection, or one-to-one function) is a function f that maps distinct elements to distinct elements; that is, f(x1) = f(x2) implies x1 = x2. (Equivalently, x1 ≠ x2 implies f(x1) ≠ f(x2) in the equivalent contrapositive statement.)

What does the inject method do in Ruby?

When called, the inject method will pass each element and accumulate each sequentially. To break this down even further, inject takes the first element in your collection and uses that as the base 'sum'. It then takes the next element (or the second element in the array) and then adds them together.

How do you use reduce in Ruby?

Ruby reduce In Ruby, the reducer is a method called reduce . A popular requirement is to reduce a list of numbers into a single value by adding them together (aka. performing a sum operation). You can pass the reduce method a starting value (i.e. 0 in the example below), and a block.

How do I use collect in Ruby?

The collect() of enumerable is an inbuilt method in Ruby returns a new array with the results of running block once for every element in enum. The object is repeated every time for each enum. In case no object is given, it return nil for each enum.


You can think of the first block argument as an accumulator: the result of each run of the block is stored in the accumulator and then passed to the next execution of the block. In the case of the code shown above, you are defaulting the accumulator, result, to 0. Each run of the block adds the given number to the current total and then stores the result back into the accumulator. The next block call has this new value, adds to it, stores it again, and repeats.

At the end of the process, inject returns the accumulator, which in this case is the sum of all the values in the array, or 10.

Here's another simple example to create a hash from an array of objects, keyed by their string representation:

[1,"a",Object.new,:hi].inject({}) do |hash, item|
  hash[item.to_s] = item
  hash
end

In this case, we are defaulting our accumulator to an empty hash, then populating it each time the block executes. Notice we must return the hash as the last line of the block, because the result of the block will be stored back in the accumulator.


inject takes a value to start with (the 0 in your example), and a block, and it runs that block once for each element of the list.

  1. On the first iteration, it passes in the value you provided as the starting value, and the first element of the list, and it saves the value that your block returned (in this case result + element).
  2. It then runs the block again, passing in the result from the first iteration as the first argument, and the second element from the list as the second argument, again saving the result.
  3. It continues this way until it has consumed all elements of the list.

The easiest way to explain this may be to show how each step works, for your example; this is an imaginary set of steps showing how this result could be evaluated:

[1, 2, 3, 4].inject(0) { |result, element| result + element }
[2, 3, 4].inject(0 + 1) { |result, element| result + element }
[3, 4].inject((0 + 1) + 2) { |result, element| result + element }
[4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
[].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
(((0 + 1) + 2) + 3) + 4
10

The syntax for the inject method is as follows:

inject (value_initial) { |result_memo, object| block }

Let's solve the above example i.e.

[1, 2, 3, 4].inject(0) { |result, element| result + element }

which gives the 10 as the output.

So, before starting let's see what are the values stored in each variables:

result = 0 The zero came from inject(value) which is 0

element = 1 It is first element of the array.

Okey!!! So, let's start understanding the above example

Step :1 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }

Step :2 [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }

Step :3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }

Step :4 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }

Step :5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }

Here Bold-Italic values are elements fetch from array and the simply Bold values are the resultant values.

I hope that you understand the working of the #inject method of the #ruby.


The code iterates over the four elements within the array and adds the previous result to the current element:

  • 1 + 2 = 3
  • 3 + 3 = 6
  • 6 + 4 = 10