24

我有一个像这样的哈希:

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递归的。我怎样才能做到这一点?

4

5 回答 5

40

以下是在 Ruby 中进行深度复制的方法

d = Marshal.load( Marshal.dump(h) )
于 2012-01-03T10:13:21.467 回答
3

如果你在 Rails 中:Hash.deep_dup

于 2015-11-23T11:22:22.033 回答
2

如果这Marchal #dump/load对不起作用,对于有一个Hash's method #deep_dup,所以你可以:

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

h1 = h.deep_dup
于 2014-05-15T12:48:32.647 回答
1

这是一个相当老的问题的答案,但我在实现类似的东西时偶然发现了它,我想我会加入一个更有效的方法。

对于像上面这样简单的两级深度哈希,您还可以执行以下操作:

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

我对包含 4k 个元素的散列进行了测试,每个元素有几百个字节,它比 Marshal.dump/load 快 50%

当然,它并不完整,因为如果你有一个散列,例如,'project_name' 字段的值,它就不起作用,但是对于一个简单的 2 级散列,它工作得很好/更快。

于 2013-10-09T20:02:56.610 回答
0

另一种选择是使用 full_dup gem(完全公开:我是该 gem 的作者),它处理数组、哈希、结构,并且可以扩展到用户定义的类。

要使用:

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

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

于 2018-01-31T16:29:49.027 回答