我有一个数组'a',后来我设置了一个新数组'b'等于'a'。当我从任一数组中删除一个元素时,它们都会更改而不是显式引用的数组。我认为这是因为他们指向同一个底层对象?
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"]
答案 0 :(得分: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
答案 1 :(得分: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#dup和Object#clone所做的“浅层”复制。
幸运的是,使用Marshal#dump和Marshal#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"]
提醒一句:Marshal文件在所有版本的Ruby中都不可移植。