【问题标题】:Actual Hash getting modified when copy is modified in ruby在 ruby​​ 中修改副本时实际哈希被修改
【发布时间】:2016-03-17 06:50:19
【问题描述】:

我正在尝试复制一个哈希,然后修改哈希的副本。但是当我将副本与原始副本进行比较时,甚至原始哈希值也被修改了。 我试过使用this:

def deep_copy(o)
  Marshal.load(Marshal.dump(o))
end

h1 = {:a => 'foo'}
h2 = deep_copy(h1)
h1[:a] << 'bar'
p h2 

我也试过this:

def dumpable_hash(h)
  return h unless h.default_proc
  copy = h.clone  
  copy.default = nil # clear the default_proc
  copy
end

哈希对象(我想复制并保持其原始未修改):

@original = {0=>{0=>[0, 4, 5, 6], 2=>[3, 7], 1=>[1, 2]}, 1=>{0=>[0, 4, 5, 6], 2=>[1], 1=>[2, 3, 7]}, 2=>{0=>[0, 4, 6], 1=>[1, 2, 5], 2=>[3, 7]}, 3=>{0=>[0, 4], 2=>[1, 2, 3, 6, 7], 1=>[5]}, 4=>{0=>[4], 2=>[1, 5], 1=>[2, 3, 6, 7, 0]}, 5=>{1=>[0, 1, 2, 5], 2=>[3, 6, 7], 0=>[4]}, 6=>{1=>[0, 1, 2, 5, 4], 2=>[3, 6, 7], 0=>[]}}

尝试将原件复制到另一个对象中,也使用给定的答案。

用于更新其克隆的方法,

 #outer loop
 (1..5).each do |i|   
 #assigning original to another object in every loop
 copy = @original.clone
       (-6..0).each do |row|                    
            if copy[row.abs][0].include? k
                copy[row.abs][0] -= [k]
                copy[row.abs][1] += [k]
                puts "row #{row.abs}, col #{k}"
                break
            end
        end
    end

当循环结束时,originalcopy 都会更新。 请帮忙,我已经尝试了一个小时。

【问题讨论】:

  • 您使用的是哪个版本的 ruby​​(或 irb?)?我已经使用 ruby​​ 版本 1.9.3、2.0 和 2.3 尝试了您的 deep_copy() 示例,但没有发现任何问题。也许您还可以更明确地说明您遇到的问题。
  • 我仍然无法修复它,我猜是因为嵌套哈希。
  • @peak,请查看更新后的问题。

标签: ruby hash


【解决方案1】:

如果想将一个哈希值复制到另一个哈希值,您可以这样做。然后您可以操作复制的哈希,甚至可以在循环中进行操作。然后为您的任务操作复制的哈希。在这里它复制哈希的键值对,

@original = {0=>{0=>[0, 4, 5, 6], 2=>[3, 7], 1=>[1, 2]}, 1=>{0=>[0, 4, 5, 6], 2=>[1], 1=>[2, 3, 7]}, 2=>{0=>[0, 4, 6], 1=>[1, 2, 5], 2=>[3, 7]}, 3=>{0=>[0, 4], 2=>[1, 2, 3, 6, 7], 1=>[5]}, 4=>{0=>[4], 2=>[1, 5], 1=>[2, 3, 6, 7, 0]}, 5=>{1=>[0, 1, 2, 5], 2=>[3, 6, 7], 0=>[4]}, 6=>{1=>[0, 1, 2, 5, 4], 2=>[3, 6, 7], 0=>[]}}
copy = Hash.new
@original.each do |k, v|
   copy[k] = v.dup    
end
p copy #prints the copied hash

【讨论】:

  • 非常感谢。它通过使用循环复制哈希来工作。
【解决方案2】:

我认为您需要在此处执行 deep_dup 以将一个哈希内容与另一个完全分开。

h1 = {a: "foo"}
h2 = h1.deep_dup
h2[:a] << "bar"
puts h2   #returns {:a => "foobar"}
puts h1   # returns {:a => "foo"}

【讨论】:

  • 如果我使用 deep_dup,它会显示 undefined method `deep_dup' for #&lt;Hash:0x9d3bea0&gt; (NoMethodError)`。我正在尝试解决在线编码环境中的问题,但无法加载任何外部库。
  • deep_dup 仅是主动支持
【解决方案3】:

使用dup

h1 = {a:1, b:2}
h2 = h1.dup
h2[:c] = 3
puts h1
{:a=>1, :b=>2} 
puts h2
{:a=>1, :b=>2, :c=>3} 

如果您有嵌套哈希,可以使用 ActiveSupport deep_dup

def deep_dup
  each_with_object(dup) do |(key, value), hash|
    hash[key.deep_dup] = value.deep_dup
  end
end

【讨论】:

    【解决方案4】:

    您正在修改原始哈希(附加到 h1 哈希)。修改深拷贝的,可以看到原来的还是原来的样子,

    def deep_copy(o)
       Marshal.load(Marshal.dump(o))
    end
    h1 = {:a => 'foo'}
    h2 = deep_copy(h1)
    h2[:a] << 'bar'
    p h2 #prints the cloned one
    p h1 #prints the original one
    

    有关编组库here 的更多信息,请参阅此处。

    【讨论】:

    • 我收到此错误,`dump': can't dump hash with default proc (TypeError)`
    • 您能否澄清一下,您是在哪个在线编码环境中获得的?
    • 现在我无法在我的本地环境中执行此操作,如果您可以尝试我在问题中给出的上述示例,因为我无法实现这一点。可能是我遗漏了什么吗?
    • 您在本地环境中使用的 ruby​​ 版本是什么?
    • 我是ruby 1.9.3p484 (2013-11-22 revision 43786) [i686-linux]
    猜你喜欢
    • 1970-01-01
    • 2016-12-16
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多