Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deeper explanation of reduce / inject method in ruby

I've been racking my brains around this for some time.

When using reduce - why is the first element returned without executing the operation defined in the block? Or am I missing a crucial point in how reduce works?

In the following example:

arr = [1, 3, 5]

arr.reduce {|sum, n| sum + (n * 3) }
#=> 25

I would have expected the result to be 27.

Since:

0 + (1 * 3) = 3
3 + (3 * 3) = 12
12 + (5 * 3) = 27

After some time playing around with it I figured out that in the first "tick" - the object from the array just get's added to the sum instead of being multiplied. So that the calculation is more like:

??? = 1
1 + (3 * 3) = 10
10 + (5 * 3) = 25

Could someone help me figure out where I've gotten off the path?

like image 759
Peter Piper Avatar asked Dec 21 '18 13:12

Peter Piper


People also ask

What does the reduce method do in Ruby?

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.

What does inject mean in Ruby?

Inject applies the block result + element. to each item in the array. For the next item ("element"), the value returned from the block is "result". The way you've called it (with a parameter), "result" starts with the value of that parameter. So the effect is adding the elements up.

What does .select do in Ruby?

Array#select() : select() is a Array class method which returns a new array containing all elements of array for which the given block returns a true value. Return: A new array containing all elements of array for which the given block returns a true value.

What does :+ mean in Ruby?

inject(:+) is not Symbol#to_proc, :+ has no special meaning in the ruby language - it's just a symbol.


2 Answers

It's in the docs.

If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.

like image 113
Sergio Tulentsev Avatar answered Oct 12 '22 02:10

Sergio Tulentsev


I had a similar issue with the default values in Ruby inject/reduce methods, so I've tried to visualize it:

default values vizualized

like image 36
Rich Steinmetz Avatar answered Oct 12 '22 00:10

Rich Steinmetz