Более глубокое объяснение метода уменьшения / ввода в ruby - PullRequest
0 голосов
/ 21 декабря 2018

Я уже некоторое время ломал голову над этим.

При использовании Reduce - почему первый элемент возвращается без выполнения операции, определенной в блоке?Или я упускаю важный момент в том, как работает Reduce?

В следующем примере:

arr = [1, 3, 5]

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

Я бы ожидал, что результат будет 27 .

Так как:

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

Через некоторое время поиграв с ним, я понял, что в первом «тике» - объект из массива просто прибавляется к сумме, а не умножается,Так что расчет выглядит примерно так:

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

Может ли кто-нибудь помочь мне выяснить, где я сошел с пути?

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Я думаю, что объяснение в помощи методов в этом случае:

[1] pry(main)> cd Array
[2] pry(Array):1> ? reduce

From: enum.c (C Method):
Owner: Enumerable
Visibility: public
Signature: reduce(*arg1)
Number of lines: 33

Combines all elements of enum by applying a binary
operation, specified by a block or a symbol that names a
method or operator.

The inject and reduce methods are aliases. There
is no performance benefit to either.

If you specify a block, then for each element in enum
the block is passed an accumulator value (memo) and the element.
If you specify a symbol instead, then each element in the collection
will be passed to the named method of memo.
In either case, the result becomes the new value for memo.
At the end of the iteration, the final value of memo is the
return value for the method.

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.


   # Sum some numbers
   (5..10).reduce(:+)                             #=> 45
   # Same using a block and inject
   (5..10).inject { |sum, n| sum + n }            #=> 45
   # Multiply some numbers
   (5..10).reduce(1, :*)                          #=> 151200
   # Same using a block
   (5..10).inject(1) { |product, n| product * n } #=> 151200
   # find the longest word
   longest = %w{ cat sheep bear }.inject do |memo, word|
      memo.length > word.length ? memo : word
   end
   longest                                        #=> "sheep"

Так что вам нужно указать первое напоминание как 0, в вашем случае это одно:

[4] pry(Array):1> [1,3,5].reduce(0) {|sum, n| sum + (n * 3) }
=> 27
0 голосов
/ 21 декабря 2018

Он находится в документах .

Если вы явно не указали начальное значение для заметки, то первый элемент коллекции используется в качестве начального значения памятки.

...