为什么在课程中使用Rubymonk中的额外声明" 7.1迭代,过滤和转换"

时间:2015-08-02 14:31:48

标签: ruby methods return

在下面的Rubymonk示例中,为什么:

[4, 8, 15, 16, 23, 42].inject(0) do |accumulator, iterated|
  accumulator += iterated
  accumulator
end

而不是

[4, 8, 15, 16, 23, 42].inject(0) do |accumulator, iterated|
  accumulator += iterated
  #accumulator
end

结果是一样的不是吗?我认为最后一个累积器'线是不必要的。

https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/44-collections/lessons/98-iterate-filtrate-and-transform#solution4313

2 个答案:

答案 0 :(得分:1)

是的,只要块的返回值为accumulator,就可以使用两者。我认为Rubymonk的例子更明确。如果您查看custom_inject示例,您会更好地理解它。

答案 1 :(得分:1)

Enumerable#inject(又名reduce)是一只奇怪的(但是很强大的)鸟。如果返回一个名为" memo"的对象。备忘录的值通常是数字,字符串,数组或散列,但它可以是任何ruby对象。

第一个块变量保存备忘录的值。当每个元素传递到块中时,备忘录的值被设置为等于先前块计算的结果。例如,假设块看起来像这样:

{ |memo,x| memo + x }

进一步假设备忘录的初始值为零(我在下面讨论),x的第一个值是3。然后是

memo + x #=> 0 + 3 => 3

memo设置为3x设置为等于传递给块的下一个值。假设该值为4。然后memo更新为:

memo + x #=> 3 + 4 => 7

现在假设编写了块:

{ |memo,x| memo += x }

最初,memo等于零,x等于3.我们因此计算:

memo += x #=> memo = memo + 3 => 0 + 3 => 3
  #=> 3

即,值memo现在是3'. As before,备忘录is updated to equal the value of the block calculation, which we just saw was 3 . When x = 4 ,备忘录is computed in the block to be 7 {{1 memo , and then 7`)因为这是块计算的结果。

如您所见,当块包含is set to that same value (时,memo += x的值计算两次:首先在块计算中;第二,它被更新为等于块计算的值,即刚刚计算的memo的值。所以计算如下:

memo

除此之外:因为备忘录被分配了块计算的值,所以最后一行(memo = 0, x = 3, memo #=> 3 (after memo += 3), them memo is set to 3 memo = 3, x = 4, memo #=> 7 (after memo += 4), them memo is set to 7 ):

tot

是多余的。

总之,arr.inject(0) do |tot,x| tot += x tot end #=> 6 { |memo,x| memo+x }产生相同的结果,但前者更有效,因为它只为传递给块的每个元素计算{ |memo,x| memo += x }一次。

memo的初始值怎么样?如果将对象传递给块的方法具有参数,则该参数的值是memo的初始值。如果它没有参数,则memo设置为等于传递给块的第一个值,并且当下一个元素传递给块时块计算开始。例如,假设我们希望总结以下元素:

memo

我们可以写:

arr = [1,2,3]

arr.inject(0) { |tot,x| tot+x }
  #=> 6

这里我们得到相同的结果,所以我们使用哪种形式是否重要?假设:

arr.inject    { |tot,x| tot+x }
  #=> 6

然后:

arr = []

arr.inject(0) { |tot,x| tot+x }
  #=> 0

因此,如果可以在空数组上调用arr.inject { |tot,x| tot+x } #=> nil ,请使用生成所需结果的表单。在大多数情况下,这可能是第一种形式。

我们可以在这里使用更短的表格:

inject

但你或许应该将其留在另一天。