我有一个哈希:
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
是另一个哈希对象。
我希望哈希是递归的duped
或cloned
。我怎样才能做到这一点?
答案 0 :(得分:39)
以下是如何在Ruby中制作深层副本
d = Marshal.load( Marshal.dump(h) )
答案 1 :(得分:2)
如果Marchal
#dump/load
对不起作用,rails有一个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处理复杂的数据关系,包括具有循环或递归的关系。