0

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

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

# 这将打印 [[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

# 这打印 [[2, 2, 2], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

4

3 回答 3

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构造函数默认参数的原因,因为它们并不总是按您期望的方式工作。

于 2012-08-10T02:49:14.407 回答
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也有两个构造函数,而且更加棘手

于 2012-08-10T14:37:35.067 回答
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],等等。

于 2012-08-10T02:46:30.030 回答