Ruby中新(嵌套)数组的奇怪行为

时间:2012-08-10 02:38:03

标签: ruby

为什么两段代码都没有打印相同的东西。我打算让第一部分产生第二部分

的输出
a=Array.new(5,Array.new(3))
for i in (0...a[0].length)
  a[0][i]=2
end
p a
  

#the print [[2,2,2],[2,2,2],[2,2,2],[2,2,2],[2,2,2]] *

a=Array.new(5).map{|d|d=Array.new(3)}
for i in (0...a[0].length)
  a[0][i]=2
end
p a
  

#the print [[2,2,2],[nil,nil,nil],[nil,nil,nil],[nil,nil,nil],[nil,nil,nil]]

3 个答案:

答案 0 :(得分:3)

这一个

a=Array.new(5,Array.new(3))

创建一个包含相同数组对象的数组五次。这有点像这样:

a = []
b = a
a[0] = 123
puts b[0] #=> 123

这一个:

a=Array.new(5).map{ Array.new(3) }

为父数组中的每个项创建一个新的3项数组。因此,当您更改第一个项目时,它不会触及其他项目。

这也是为什么你不应该真正使用ArrayHash构造函数默认参数的原因,因为它们并不总是像你期望的那样工作。

答案 1 :(得分:1)

Array.new(5,Array.new(3))

在第一个示例中,您的数组包含对同一数组的5个引用。您可以使用Array.new(3)创建一个数组的单个实例,该引用将用于初始化的5个数组中的每个数组。修改a[0][0]时,您还要修改a[1][0]a[2][0]等。它们都是对同一数组的引用。

Array.new(5).map{ |d| Array.new(3) }

在第二个示例中,您的数组包含5个不同的数组。您的块被调用5次,Array.new(3)被调用5次,并且创建了5个不同的数组。 a[0]是与a[1]等不同的数组

答案 2 :(得分:1)

以下是等效的:

Array.new(5,Array.new(3))

[Array.new(3)] * 5

inside = Array.new(3); [inside, inside, inside, inside, inside]

它们都将生成包含相同数组的数组。我的意思是完全相同的对象。这就是为什么如果你修改它的内容,你会看到新值5次。

如果需要独立数组,您需要确保“内部”数组不是同一个对象。这可以通过不同方式实现,例如:

Array.new(5){ Array.new(3) }

5.times.map { Array.new(3) }

Array.new(5).map { Array.new(3) }

# or dup your array manually:
inside = Array.new(3); [inside.dup, inside.dup, inside.dup, inside.dup, inside]

请注意,您首先使用的Array.new(5, [])表单不会为您复制obj,它会重复使用它。由于这不是您想要的,您应该使用块形式Array.new(5){ [] },它将调用块5次,并且每次创建一个新数组。

Hash类还有两个构造函数,even more tricky