【问题标题】:Deeper explanation of reduce / inject method in rubyruby中reduce/inject方法的深入解释
【发布时间】:2019-05-21 23:14:54
【问题描述】:

我已经为此绞尽脑汁了一段时间。

使用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

玩了一段时间后,我发现在第一个“tick”中 - 数组中的对象只是被添加到总和而不是相乘。这样计算更像:

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

有人可以帮我弄清楚我在哪里偏离了道路吗?

【问题讨论】:

  • [1, 3, 5].reduce(0) { |sum, n| sum + n * 3 } 是您想要的——它使用初始值 0(或您传递的任何值),因此返回 27 而不是 25
  • 在你的第一个方程中,零是从哪里来的?不在数组中?
  • @JörgWMittag - 我希望 sum 的初始值默认为零。
  • 想象一下,如果您想计算阶乘。乘法的中性元素是 1,而不是 0。或者,如果您想构造一些字符串。字符串连接的中性元素是空字符串。或者,你想建立一个哈希;哈希合并的中性元素是空哈希。为了选择正确的中性元素,Ruby 必须读懂你的想法才能知道你想要计算的是什么!如果你这样想,应该清楚为什么元素只能来自数组。

标签: ruby functional-programming reduce


【解决方案1】:

它在the docs

如果没有显式指定memo的初始值,则collection的第一个元素作为memo的初始值。

【讨论】:

  • Peter 初始备忘录非常重要——尤其是当您考虑在没有初始备忘录的情况下尝试 reduce 一个空数组时会发生什么...
【解决方案2】:

我对 Ruby 注入/减少方法中的默认值有类似的问题,所以我尝试visualize it

【讨论】:

  • 我在此期间得到了它,但这是一个非常好的解释!
  • 是的,已经有一段时间了,但希望这可以避免一些在这里偶然发现它的人的大脑杂技 :) 感谢您接受它作为答案!
【解决方案3】:

我认为在这种情况下,解释是在方法的帮助下:

[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

【讨论】:

    猜你喜欢
    • 2018-12-03
    • 2013-04-03
    • 1970-01-01
    • 2021-09-09
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多