我必须更新数组,并且在传递给+=
的块内的不同代码行中使用了<<
和Array#each_with_object
:
(1..5).each_with_object([]) do |i, a|
puts a.inspect
a += [i]
end
输出:
[]
[]
[]
[]
[]
(1..5).each_with_object([]) do |i, a|
puts a.inspect
a << [i]
end
输出:
[]
[1]
[1,2]
[1,2,3]
[1,2,3,4]
+=
运算符不会更新原始数组。为什么?我在这里缺少什么?
答案 0 :(得分:4)
在each_with_object
中,所谓的备忘录对象在迭代中很常见。您需要修改该对象才能执行有意义的操作。 +=
运算符是+
和赋值的语法糖,它不会修改接收者,因此迭代无效。如果您使用<<
或push
等方法,则会生效。
另一方面,在inject
中,所谓的memo对象是块的返回值,你不需要修改对象,但是你需要返回值想要下一次迭代。
答案 1 :(得分:4)
我很清楚+ =运算符没有更新原始数组。为什么呢?
因为the documentation这样说(强调我的):
ary + other_ary
→new_ary
连接 - 返回通过将两个数组连接在一起以生成第三个数组而构建的 new 数组。
[ 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" ]
请注意
x += y
与
相同x = x + y
这意味着它会生成 new 数组。因此,在数组上重复使用
+=
可能效率很低。另见
#concat
。
与<<
ary << obj
→ary
追加 - 将给定对象推送到此数组的末尾。该表达式返回数组本身,因此可以将多个附加链接在一起。
[ 1, 2 ] << "c" << "d" << [ 3, 4 ] #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
Array#+
的文档清楚地表明返回了 new 数组(实际上不少于4次)。这与Ruby中+
方法的其他用法一致,例如: Bignum#+
,Fixnum#+
,Complex#+
,Rational#+
,Float#+
,Time#+
,String#+
,BigDecimal#+
,{{ 3}},Date#+
,Matrix#+
,Vector#+
,Pathname#+
和Set#+
。