2013-06-19 81 views
0

如果下面的代碼是在IRB控制檯運行:爲什麼數組連接導致(無限?)嵌套數組?

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

結果是[[[...], 1]]

其後arr[0],arr[0][0],arr[0][0][0]等產生相同的輸出。

這種說法有道理,因爲我無法顯示任意數量的嵌套權限?

但是,arr[0][1]產生零(而不是1)是什麼? 但arr[0][0][1]打印1

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

則:

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

這是怎麼回事?什麼是實際創建的結構?這個結構遞歸有多深? nils從哪裏來?

回答

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]是指同一個對象。
如果你想只插入你應該先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. 
+0

權brainfart。實際上寫出來確實解釋了nils和尺寸。但是,爲什麼它不簡單地將arr設置爲[[[],1],1]。它爲什麼會緩和,而它的遞歸有多深? –

+0

@AbrahamP我編輯了我的答案和解釋。 – oldergod

+0

我真的很抱歉,我覺得我錯過了一些真正的根本。 但是,arr = [[],1] arr [0] << [[],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 
+0

right brainfart。實際上寫出來確實解釋了nils和尺寸。但是,爲什麼它不簡單地將arr設置爲[[[],1],1]。它爲什麼會緩和,而它的遞歸有多深? –