我有这段代码创建了一个数组数组([[],[],[]]
)和一个迭代器,它试图用数字填充相应的数组(如下所示)
array = Array.new(3,[])
10.times do
array[0] << 2
array[1] << 3
array[2] << 4
end
当我执行此代码时,我希望看到这个
[[2,2,2,2,etc....],[3,3,3,3,etc...],[4,4,4,4,4...etc]]
但我得到了这个:
[[2,3,4,2,3,4,2,3,4....repeat],[2,3,4,2,3,4,2,3,4....repeat],[2,3,4,2,3,4,2,3,4....repeat]]
我试图用byebug
来完成它,这对我来说毫无意义。这是怎么回事?
答案 0 :(得分:5)
Array.new(3, [])
不等同于[[],[],[]]
。它相当于array = []; [array, array, array]
,这是对同一个数组的三个引用的数组。在array[0] << 2
之后,您有[[2], [2], [2]]
,因为所有三个元素都指向同一个数组。
你想要的是Array.new(3) { [] }
,其中一个块指定默认值;这样,为每个元素创建了一个新的[]
。
更好的是,您的整个代码可以写成:
Array.new(3) { |i| Array.new(10, i + 2) }
答案 1 :(得分:1)
您使用的初始化程序旨在与不可变对象一起使用,例如创建n倍于同一整数的数组。对于可变对象,请使用块版本。这是解决问题的方法:
array = Array.new(3) { [] }
10.times do
array[0] << 2
array[1] << 3
array[2] << 4
end
array[0]
#=> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
答案 2 :(得分:1)
阅读文档
第二个参数使用对该数组的引用填充数组 宾语。因此,仅在您需要时才建议使用 使用本机不可变对象(如符号)实例化数组, 数字,无论是真是假。
要创建具有单独对象的数组,可以传递块 代替。这种方法可以安全地与可变对象一起使用,例如 哈希,字符串或其他数组:
Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]
这也是构建多维数组的快捷方法:
empty_table = Array.new(3) { Array.new(3) }
因此,您的代码第一行应该是
array = Array.new(3) { Array.new(3) }