在下面的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
结果是一样的不是吗?我认为最后一个累积器'线是不必要的。
答案 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
设置为3
,x
设置为等于传递给块的下一个值。假设该值为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
但你或许应该将其留在另一天。