Ruby Array.new 初始化的一点点奇怪的地方

Kirisames · 2023年10月22日 · 最后由 u1450154824 回复于 2023年10月23日 · 312 次阅读

#关于 Array.new 方法创建出的“二维数组”的疑惑

官方文档中关于 Array.new 的使用方法如下:

Array.new(3)       #=> [nil, nil, nil]
Array.new(3, true) #=> [true, true, true]

Array.new(4) {Hash.new}    #=> [{}, {}, {}, {}]
Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]

empty_table = Array.new(3) {Array.new(3)}
#=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

当我使用:

Array.new(3, Array.new(4, false)) # => [[false, false], [false, false], [false, false]]

依旧能“正常”创建二维数组。 但是在使用上却有着实际的不同。

一个例子便是:

temp = Array.new(3,Array.new(2,false))
# => [[false, false], [false, false], [false, false]]
temp[1][1] = true #=> true
temp.inspect #=> "[[false, true], [false, true], [false, true]]"

实际上对“单元”的修改变成了对整列的修改。

对此,我希望讨论解答下面几个问题:

1. 造成这个现象的原因是什么?

我个人初步猜测是 temp[1][1] 的修改是指向整个列的,但是查询还是可以访问到对应的单元

2. 如果只想对某个单元进行修改(如例子中的 temp[1][1])应该如何操作?

3. 是否有可能将这种数组转化为一般使用的数组(Array.new(3) {Array.new(2, false)}) ?

Note that the second argument populates the array with references to the same object.

第二个参数传的是引用,意味着第一层数组的每一项都指向同一个 array 对象。

arr = Array.new(2, false)
temp = Array.new(3,  arr)
# => [[false, false], [false, false], [false, false]]
arr[1] = true
temp.inspect #=> "[[false, true], [false, true], [false, true]]"

正如 rei 所说的 是引用,你可以打印出他的 object_id 进行验证:

3.2.1 :006 > temp = Array.new(3,Array.new(2,false))
 => [[false, false], [false, false], [false, false]]
3.2.1 :007 > temp.each {|line| puts line.object_id }
190820
190820
190820

Array.new(3) { Array.new(2, false) }

试试这个

需要 登录 后方可回复, 如果你还没有账号请 注册新账号