为什么我的 2-D Ruby 数组的多个值发生变化,尽管只更改了其中一个值?

问题描述 投票:0回答:2

我有以下代码

visited = [[false]*4] * 3

它向我展示了二维数组

[[false, false, false, false], [false, false, false, false], [false, false, false, false]]

现在我希望更改第 1 行第 2 列的元素,如下所示:

[[false, false, false, false], [false, false, false, false], [false, false, false, false]]
                                         ^

所以我做了以下事情:

visited[1][2] = 1

但是现在当我检查二维数组时,我得到以下输出:

puts visited.inspect
> [[false, false, 1, false], [false, false, 1, false], [false, false, 1, false]]

我似乎无法弄清楚为什么同一列索引处的所有行都填充为 1?

编辑: 我尝试通过手动输入所有元素(不乘以数组)来初始化我的数组

visited
,并且效果很好。我想知道为什么会这样呢?如果这不是这样做的正确约定,我深表歉意,我来自 Python 背景。

ruby
2个回答
4
投票

您拥有对 same 数组的三个引用。其中一个的改变就是所有三个的改变,因为根本不存在三个。

这可以通过使用

#object_id
看到。

irb(main):005:0> visited = [[false]*4] * 3
=> [[false, false, false, false], [false, false, false, false], [false, false, false, false]]
irb(main):006:0> visited.map(&:object_id)
=> [70221746802920, 70221746802920, 70221746802920]

现在考虑一下如果我们将一个块传递给

Array#new
会发生什么。数组
[false]
是块的本地数组,因此每次调用该块时,都会生成一个新的。

irb(main):008:0> visited = Array.new(3) { [false] * 4 }
=> [[false, false, false, false], [false, false, false, false], [false, false, false, false]]
irb(main):009:0> visited.map(&:object_id)
=> [70221746635240, 70221746635200, 70221746635160]

所有三个数组都有唯一的对象 ID。

irb(main):010:0> visited[0][2] = 42
=> 42
irb(main):011:0> visited
=> [[false, false, 42, false], [false, false, false, false], [false, false, false, false]]

1
投票

这是因为在 Ruby 中一切都是对象,并且 Ruby 默认传递对该对象的引用。因此,您的 2D 数组由对 same 四成员数组的三个引用组成。你对一个人所做的事,也会对所有三个人做。

© www.soinside.com 2019 - 2024. All rights reserved.