我正在尝试使用默认值的另一个哈希来初始化ruby中的哈希值。我想要一份深刻的副本,但我似乎只能得到一份浅色的副本。
以下是一个例子:
DEFAULT_HASH = { a: 0, b: 1 }.freeze
my_hash = DEFAULT_HASH.dup
my_hash[:a] = 4
现在“my_hash”和DEFAULT_HASH中a的值是4.我只想改变哈希值中的值。
我也尝试了其他方法:
my_hash = {}.merge DEFAULT_HASH
和
my_hash.merge! DEFAULT_HASH
所有这些产生相同的效果。实现这种初始化的最佳方法是什么。我也在使用嵌套哈希,这增加了一些复杂性。
即。我的DEFAULT_HASH看起来像:
DEFAULT_HASH = { a:{a:1, b:2}, b:{a:2, b:1} }
这会影响如何做到吗?
编辑: 嵌套哈希案例
DEFAULT_HASH = { a:{a:1, b:2}, b:{a:2, b:1} }
=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
a=DEFAULT_HASH.dup
=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
a[:b][:a]=12
=> 12
DEFAULT_HASH
=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>12, :b=>1}}
答案 0 :(得分:3)
您可以使用Marhal::dump和Marshal::load轻松创建自己的深度复制方法:
def deep_dup(obj)
Marshal.load(Marshal.dump(obj))
end
obj
可以是任何Ruby对象(例如,数组和散列的嵌套混合)。
h = { a: { b: { c: { d: 4 } } } }
g = deep_dup(h) #=> {:a=>{:b=>{:c=>{:d=>4}}}}
g[:a][:b][:c][:d] = 44 #=> 44
g #=> {:a=>{:b=>{:c=>{:d=>44}}}}
h #=> {:a=>{:b=>{:c=>{:d=>4}}}}
对于你的例子:
DEFAULT_HASH = { a: { a:1, b:2 }, b: { a:2, b:1 } }
#=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
h = deep_dup(DEFAULT_HASH)
#=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
h[:b][:a] = 12
#=> 12
h #=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>12, :b=>1}}
DEFAULT_HASH
#=> {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
答案 1 :(得分:2)
对于@ pjs来说,Hash#dup
将为散列的顶级“做正确的事”。但是对于嵌套哈希,它仍然会失败。
如果您愿意使用某个宝石,请考虑使用deep_enumerable,这是我为此目的编写的一个宝石(等等)。
DEFAULT_HASH = { a:{a:1, b:2}, b:{a:2, b:1} }
dupped = DEFAULT_HASH.dup
dupped[:a][:a] = 'updated'
puts "dupped: #{dupped.inspect}"
puts "DEFAULT_HASH: #{DEFAULT_HASH.inspect}"
require 'deep_enumerable'
DEFAULT_HASH = { a:{a:1, b:2}, b:{a:2, b:1} }
deep_dupped = DEFAULT_HASH.deep_dup
deep_dupped[:a][:a] = 'updated'
puts "deep_dupped: #{deep_dupped.inspect}"
puts "DEFAULT_HASH: #{DEFAULT_HASH.inspect}"
输出:
dupped: {:a=>{:a=>"updated", :b=>2}, :b=>{:a=>2, :b=>1}}
DEFAULT_HASH: {:a=>{:a=>"updated", :b=>2}, :b=>{:a=>2, :b=>1}}
deep_dupped: {:a=>{:a=>"updated", :b=>2}, :b=>{:a=>2, :b=>1}}
DEFAULT_HASH: {:a=>{:a=>1, :b=>2}, :b=>{:a=>2, :b=>1}}
或者,您可以尝试以下方式:
def deep_dup(h)
Hash[h.map{|k, v| [k,
if v.is_a?(Hash)
deep_dup(v)
else
v.dup rescue v
end
]}]
end
注意,这最后一个函数远不及deep_enumerable
测试。
答案 2 :(得分:-1)
不.freeze
给出了以下结果:
irb(main):001:0> DEFAULT_HASH = { a: 0, b: 1 }
=> {:a=>0, :b=>1}
irb(main):002:0> my_hash = DEFAULT_HASH.dup
=> {:a=>0, :b=>1}
irb(main):003:0> my_hash[:a] = 4
=> 4
irb(main):004:0> my_hash
=> {:a=>4, :b=>1}
irb(main):005:0> DEFAULT_HASH
=> {:a=>0, :b=>1}