Ruby递归/克隆递归

时间:2012-01-03 10:12:02

标签: ruby hash clone hash-of-hashes dup

我有一个哈希:

h = {'name' => 'sayuj', 
     'age' => 22, 
     'project' => {'project_name' => 'abc', 
                   'duration' => 'prq'}}

我需要这个哈希的副本,更改不应该影响原始哈希。

当我尝试时,

d = h.dup # or d = h.clone
d['name'] = 'sayuj1'
d['project']['duration'] = 'xyz'

p d #=> {"name"=>"sayuj1", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22}
p h #=> {"name"=>"sayuj", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22}

在这里,您可以看到原始哈希中project['duration']已更改,因为project是另一个哈希对象。

我希望哈希是递归的dupedcloned。我怎样才能做到这一点?

5 个答案:

答案 0 :(得分:39)

以下是如何在Ruby中制作深层副本

d = Marshal.load( Marshal.dump(h) )

答案 1 :(得分:2)

如果Marchal #dump/load对不起作用,有一个Hash方法#deep_dup,所以你可以:

h = {'name' => 'sayuj', 
 'age' => 22, 
 'project' => {'project_name' => 'abc', 
               'duration' => 'prq'}}

h1 = h.deep_dup

答案 2 :(得分:2)

如果你在Rails中:Hash.deep_dup

答案 3 :(得分:1)

这是一个相当古老的问题的答案,但我在实现类似的事情时遇到了这个问题,我认为我想要一个更有效的方法。

对于像上面这样简单的两级深度哈希,你也可以这样做:

d = h.inject({}) {|copy, (key, value)| 
    copy[key] = value.dup rescue value; copy
}

我使用4k元素的哈希散列运行测试,每个元素有几百个字节,比Marshal.dump / load

快约50%

当然,它并不完整,因为如果你有一个哈希值,例如'project_name'字段的值,它将无法工作,但对于一个简单的2级哈希,它可以很好/更快。< / p>

答案 4 :(得分:0)

另一个替代方法是使用full_dup gem(完全披露:我是该gem的作者)来处理数组,散列,结构,并且可以扩展到用户定义的类。

使用:

require 'full_dup'
# Other code omitted ...
d = h.full_dup

另请注意,full_dup处理复杂的数据关系,包括具有循环或递归的关系。