【问题标题】:Ruby hash.delete(:key) deleting copies and clones as wellRuby hash.delete(:key) 也删除副本和克隆
【发布时间】:2013-05-16 05:08:33
【问题描述】:

据我了解,当您将 object = 设置为另一个时,它将始终是一个引用,因此我们有像 .dup.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(在此示例中)的引用而不是副本,因为它是包含在散列中的散列数组?

【问题讨论】:

    标签: ruby hash clone dup


    【解决方案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"
    

    position 键在使用 .dup.clone 时被删除的原因是因为 tracks 键仍然引用同一个数组对象。在编组之后,tracks 键指的是一个全新的数组对象。

    【讨论】:

      【解决方案2】:

      您正在克隆 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 上的同一对象

      【讨论】:

        猜你喜欢
        • 2011-05-08
        • 2015-08-08
        • 1970-01-01
        • 2021-01-25
        • 2011-08-08
        • 2012-01-11
        • 1970-01-01
        • 2012-05-07
        • 2014-11-16
        相关资源
        最近更新 更多