为什么这段代码会填充每个数组?

时间:2016-08-31 03:37:42

标签: ruby

我有这段代码创建了一个数组数组([[],[],[]])和一个迭代器,它试图用数字填充相应的数组(如下所示)

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来完成它,这对我来说毫无意义。这是怎么回事?

3 个答案:

答案 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) }