`each_with_object` 块内的 `+=` 和 `<<` 之间的区别

Difference between `+=` and `<<` inside a block for `each_with_object`

我不得不更新一个数组,我在传递给 Array#each_with_object:

的块内的不同代码运行中使用了 +=<<

代码 1

(1..5).each_with_object([]) do |i, a|
  puts a.inspect
  a += [i]
end

输出:

[]
[]
[]
[]
[]

代码 2

(1..5).each_with_object([]) do |i, a|
  puts a.inspect
  a << [i]
end

输出:

[]
[1]
[1,2]
[1,2,3]
[1,2,3,4]

+= 运算符不会更新原始数组。为什么?我在这里错过了什么?

each_with_object中,所谓的备忘录对象在迭代中很常见。您需要修改该对象才能做一些有意义的事情。 += 运算符是 + 和赋值的语法糖,它不会修改接收者,因此迭代没有效果。如果你使用像<<push这样的方法,那么它就会生效。

另一方面,在inject中,所谓的memo对象就是block的return值,不需要修改对象,但是需要return 下一次迭代所需的值。

It is clear to me that += operator is not updating the original array. Why?

因为 the documentation 这么说(强调我的):

ary + other_arynew_ary

Concatenation — Returns a new array built by concatenating the two arrays together to produce a third array.

[ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
a = [ "a", "b", "c" ]
c = a + [ "d", "e", "f" ]
c                         #=> [ "a", "b", "c", "d", "e", "f" ]
a                         #=> [ "a", "b", "c" ]

Note that

x += y

is the same as

x = x + y

This means that it produces a new array. As a consequence, repeated use of += on arrays can be quite inefficient.

See also #concat.

比较 <<

ary << objary

Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.

[ 1, 2 ] << "c" << "d" << [ 3, 4 ]
        #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]

Array#+的文档明确说返回了一个new数组(实际上不少于四次)。这与 Ruby 中 + 方法的其他用法一致,例如Bignum#+, Fixnum#+, Complex#+, Rational#+, Float#+, Time#+, String#+, BigDecimal#+, Date#+, Matrix#+, Vector#+, Pathname#+, Set#+, and URI::Generic#+.