Ruby数组+ = vs push

时间:2017-08-08 14:25:15

标签: arrays ruby

我有一个数组数组,想要将元素追加到子数组中。 + =做我想要的,但我想理解为什么不推。

我期望的行为(和+ =一起使用):

b = Array.new(3,[])
b[0] += ["apple"]
b[1] += ["orange"]
b[2] += ["frog"]

b => [[“apple”],[“orange”],[“frog”]]

使用push我将push元素附加到EACH子数组(为什么?):

a = Array.new(3,[])
a[0].push("apple")
a[1].push("orange")
a[2].push("frog")

a => [[“apple”,“orange”,“frog”],[“apple”,“orange”,“frog”],[“apple”,“orange”,“frog”]]

对此的任何帮助都非常感谢。

2 个答案:

答案 0 :(得分:10)

这里的问题是b = Array.new(3, [])使用与所有数组单元格的基值相同的对象:

b = Array.new(3, [])
b[0].object_id #=> 28424380
b[1].object_id #=> 28424380
b[2].object_id #=> 28424380

因此,当您使用b[0].push时,它会将项目添加到"每个"子数组,因为它们实际上都是相同的数组。

那么为什么b [0] + = ["值"]有效?好吧,看看红宝石文档:

  

ary + other_ary→new_ary

     

Concatenation - 返回通过将两个数组连接在一起以生成第三个数组而构建的新数组。

[ 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
  

这意味着它会生成一个新数组。因此,在数组上重复使用+ =可能效率很低。

因此,当您使用+=时,它会完全替换数组,这意味着b[0]中的数组不再与b[1]b[2]相同。

如你所见:

b = Array.new(3, [])
b[0].push("test") 
b #=> [["test"], ["test"], ["test"]]
b[0].object_id #=> 28424380
b[1].object_id #=> 28424380
b[2].object_id #=> 28424380
b[0] += ["foo"]
b #=> [["test", "foo"], ["test"], ["test"]]
b[0].object_id #=> 38275912
b[1].object_id #=> 28424380
b[2].object_id #=> 28424380

如果您想知道在初始化数组数组时如何确保每个数组都是唯一的,您可以这样做:

b = Array.new(3) { [] }

这种不同的语法允许您传递一个代码块,该代码块为每个单元格运行以计算其原始值。由于为每个单元格运行块,因此每次都会创建一个单独的数组。

答案 1 :(得分:0)

这是因为在第二个代码部分,你选择了子阵列并推送到它,如果你想要一个阵列数组,你需要将阵列推到主阵列阵列。

a = Array.new(3,[])
a.push(["apple"])
a.push(["orange"])
a.push(["frog"])

获得与第一个相同的结果。

编辑:我忘了提及,因为你用空格数组初始化数组作为元素,你会在推送元素前面有三个空元素,