1

据我了解,当您将 object = 设置为另一个时,它将始终是一个引用,因此我们有类似.dupand的方法.clone来实际创建对象的副本而不是引用。

但是,我正在复制或克隆一个哈希数组,然后当我从原始哈希中删除一个键时,它们将从副本中删除!这不应该发生,我想知道我做错了什么。

代码:

or_data = {title: 'some title', tracks: [ { name: 'track one', position: 0, 
  artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, 
  { name: 'track two', position: 1, artist: 'some other guy', 
  composer: 'beethoven', duration: '2:10' } ]  }

new_hash = or_data.dup
# or new_hash = or_data.clone, either way produces the same result

or_data[:tracks].each { |e| e.delete(:position) }

密钥也将从中:position删除new_hash

无论我使用.dup还是,都会发生这种情况.clone

我刚刚读到一篇文章说应该使用:

new_hash = Marshal.load( Marshal.dump(or_data) )

这确实有效。但为什么?因为.dup并且.clone做“浅拷贝”意味着他们将创建一个引用:tracks(在这个例子中)而不是一个副本,因为它是一个包含在哈希中的哈希数组?

4

2 回答 2

1

你不Hash object克隆Hash values。它不执行嵌套克隆。

在您的情况下,数组 ( [ { name: 'track one', position: 0, artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, { name: 'track two', position: 1, artist: 'some other guy', composer: 'beethoven', duration: '2:10' } ]) 正在引用相同的对象clonedup

于 2013-05-21T12:45:59.310 回答
1

看看下面的代码:

or_data = {title: 'some title', tracks: [ { name: 'track one', position: 0, artist: 'orignal artist', composer: 'original composer', duration: '1:30' }, { name: 'track two', position: 1, artist: 'some other guy', composer: 'beethoven', duration: '2:10' } ]  }
new_hash = or_data.dup

p "Using .dup"
p "-----------"
p "or_data : #{or_data.object_id}"
p "new_hash : #{new_hash.object_id}"

p "or_data[:tracks] :#{or_data[:tracks].object_id}"
p "new_hash[:tracks] : #{new_hash[:tracks].object_id}"


or_data[:tracks].each { |e| e.delete(:position) }


new_hash = Marshal.load( Marshal.dump(or_data) )

p "Marshalling"
p "-----------"
p "or_data : #{or_data.object_id}"
p "new_hash : #{new_hash.object_id}"

p "or_data[:tracks] :#{or_data[:tracks].object_id}"
p "new_hash[:tracks] : #{new_hash[:tracks].object_id}"

输出:

"Using .dup"
"-----------"
"or_data : 5282580"
"new_hash : 5282568"
"or_data[:tracks] :5282592"
"new_hash[:tracks] : 5282592"

"Marshalling"
"-----------"
"or_data : 5282580"
"new_hash : 5282172"
"or_data[:tracks] :5282592"
"new_hash[:tracks] : 5282112"

使用orposition时键被删除的原因是键仍然引用同一个数组对象。在 Marshalling 之后,键是指一个全新的数组对象。.dup.clonetrackstracks

于 2013-05-21T12:51:01.903 回答