为什么数组连接导致(无限?)嵌套数组?

时间:2013-06-19 05:04:48

标签: ruby arrays concatenation

如果在IRB控制台中运行以下代码:

arr = [[], 1]
arr[0]<<arr

结果为[[[...], 1]]

此后arr[0]arr[0][0]arr[0][0][0]等产生相同的输出。

这种情况有道理,因为我无法显示任意数量的嵌套吗?

然而,arr[0][1]产生的是nil(而不是1)是什么? 但arr[0][0][1]打印1

arr[0][0][0][1] => nil

然后:

arr[0][0][0][0][1] => 1

发生了什么事?实际创建的结构是什么?这个结构的深度有多大? nils来自哪里?

2 个答案:

答案 0 :(得分:1)

看看里面是什么

arr[0]
# => [[[...], 1]]

arr[0]是一个只有一个元素的数组。因此[1]将不在此数组中并返回nil。

arr[0][0]
# => [[[...]], 1]

arr[0][0]将进入顶部数组中唯一的一个元素,此元素包含两个值,因此[1]会找到一个值。

它表现得如此,因为您执行了arr[0] << arr而不是arr[0] = arr 通过执行arr = [[], 1]; arr[0] << arr,您没有将arr设置为arr[0],而是将您添加的arr设置为arr [0]的元素,这是一个数组本身。

如果你没有这样做

arr = ["whatever", 1]
# => ["whatever", 1]
arr[0] = arr
# => [[...], 1]
arr[0][1]
# => 1
arr[0][0][1]

修改

回到你的问题,为什么它成为一个递归数组。您没有将arr的值传递给arr[0],而是将其引用

arr = ["whatever", 1]
# => ["whatever", 1]
arr.object_id
# => 69999412942060
arr[0] = arr
# => [[...], 1]
arr[0].object_id
# => 69999412942060
arr[0].object_id == arr.object_id
# => true

由于arrarr[0]指的是同一个对象,因此你有Ouroboros 如果您只想插入其值,则应首先对其进行deep_copied。

arr = ["whatever", 1]
arr_copy = Marshal.load(Marshal.dump(arr)) # copy the value,
                                           # delete the object reference dependence
arr[0] = arr_copy
puts arr.inspect
# [["whatever", 1], 1] # no infinit recurrence.

答案 1 :(得分:1)

Array#size也是必不可少的,以证明为什么有时您会看到nil1作为输出:

arr = [[], 1]
arr[0]<< arr
arr.size # => 2
arr # => [[[...]], 1]

arr[0] # => [[[...], 1]]
arr[0].size # => 1
arr[0][1] # => nil

arr[0][0] # => [[[...]], 1]
arr[0][0].size # => 2
arr[0][0][1] # => 1

arr[0][0][0] # => [[[...], 1]]
arr[0][0][0].size # => 1
arr[0][0][0][1] # => nil

arr[0][0][0][0] # => [[[...]], 1]
arr[0][0][0][0].size # => 2
arr[0][0][0][0][1] # => 1