2014-01-19 32 views
0

我有一個數組'a',後來我設置了一個等於'a'的新數組'b'。當我從兩個數組中刪除一個元素時,它們都會改變,而不是顯式引用的數組。我認爲這是因爲他們指向相同的底層對象?設置一個等於另一個的數組,然後更改第一個數組而不影響第二個數組

a= ["cat","hat","dog"] 
b= a 
a.delete_at(0) 
print a 
>> a = ["hat","dog" 
print b 
>> b = ["hat","dog"] 

如何設置兩個相等的變量,但允許它們獨立於以後的操作?我在尋找的行爲是這樣的:

a= ["cat","hat","dog"] 
b= a 
a.delete_at(0) 
print a 
>> a = ["hat","dog" 
print b 
>> b = ["cat","hat","dog"] 

回答

3

使用Object#dup創建原始數組的一個副本:

a = ["cat","hat","dog"] 
b = a.dup # b now points to a duplicate of a, not a itself 

b # => ["cat","hat","dog"] 
b.delete_at(0) 

b # => ["hat","dog"] 
a # => ["cat","hat","dog"] 

爲了驗證此行爲:

a = [1, 2, 3] 
b = a 
a.object_id == b.object_id # => true, a and b point to the same objects 

a = [1, 2, 3] 
b = a.dup 
a.object_id == b.object_id # => false, a and b point to different objects 
+0

我剛剛注意到「DUP」方法在進行字符串操作時不起作用。例如,如果我做b [0] .upcase!兩個數組的第一個元素都被改變了。對此有何洞察? –

0

或許值得注意如果

a = [["cat", "pig"], "hat", "dog"] # => [["cat", "pig"], "hat", "dog"] 
b = a.dup       # => [["cat", "pig"], "hat", "dog"] 

然後

a[0].delete_at(0) 
a         # => [["pig"], "hat", "dog"] 
b         # => [["pig"], "hat", "dog"] 

這裏你需要這樣做:

a = [["cat", "pig"], "hat", "dog"] 
b = a.dup 
b[0] = a[0].dup 
a[0].delete_at(0) 
a         # => [["pig"], "hat", "dog"] 
b         # => [["cat", "pig"], "hat", "dog"] 

現在假設a是要複雜得多,比如,哈希其值是散列的數組的數組。顯然,必須注意製作a的副本,這些副本不會因刪除a的某些深層嵌套元素而受到影響。你想要的就是所謂的「深層複製」,而不是由Object#dupObject#clone所做的「淺層」複製。

幸運的是,有一個簡單的方法,使任何對象的深拷貝,使用Marshal#dumpMarshal#load

b = Marshal.load(Marshal.dump(a)) 
a[0].delete_at(0) 
a         # => [["pig"], "hat", "dog"] 
b         # => [["cat", "pig"], "hat", "dog"] 

順便說一句,Marshal也可以用來保存對象到文件供以後檢索:

File.open('myfile', 'w+') do |f| 
    Marshal.dump(a, f) 
end 

File.open('myfile') do |f| 
    c = Marshal.load(f) 
end 
c         # => [["cat", "pig"], "hat", "dog"] 

一句警告:在所有版本的Ruby中,元帥文件都不是不可移植的。

相關問題