我有以下代码
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 背景。
您拥有对 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]]
这是因为在 Ruby 中一切都是对象,并且 Ruby 默认传递对该对象的引用。因此,您的 2D 数组由对 same 四成员数组的三个引用组成。你对一个人所做的事,也会对所有三个人做。