我有一个散列-
h1 = {"a"=>{"x"=>"1","y"=>"2"}, "b"=>"z"}
我有另一个散列h2
,它基本上为h1
中的一些密钥更新了值
h2 = {"a"=>{"x"=>"3"}, "b"=>"q"}
当我做时
h1.merge(h2)
我期待它回来-
{"a"=>{"x"=>"3","y"=>"2"}, "b"=>"q"}
但它实际上给了我——{"a"=>{"x"=>"3"}, "b"=>"q"}
我需要做什么才能获得{"a"=>{"x"=>"3","y"=>"2"}, "b"=>"q"}
?
我不是在使用铁轨。ruby版本是2.6.0
Hash#merge
的工作方式是一致的:如果键在两者中都存在,那么在所有情况下,合并后的散列的键值都会替换第一个。您需要一个递归合并。
Rails中提供了一个deep_merge
。但是,如果您不使用Rails,或者它不适合您的需求,您可以很容易地推出自己的Rails。
Hash#merge
确实支持一个有帮助的块:
h1.merge(h2) { |k, old, new| (old.instance_of?(Hash) && new.instance_of?(Hash)) ?
old.merge(new) : new }
如果你只有一层深度的嵌入散列,这将起作用。如果你有任意深度的嵌套散列,你可以用deep_merge
:对Hash
进行猴子补丁
class Hash
def deep_merge(h)
self.merge(h) { |k, old, new| (old.instance_of?(Hash) && new.instance_of?(Hash)) ?
old.deep_merge(new) : new }
end
end
或者类似的东西…:(如果在这两种情况下都有散列,这将递归合并,否则,它将照常替换。你可以根据自己的口味来修改它。
在你的案例中尝试一下:
2.6.1 :008 > class Hash
2.6.1 :009?> def deep_merge(h)
2.6.1 :010?> self.merge(h) { |k, old, new| (old.instance_of?(Hash) && new.instance_of?(Hash)) ?
2.6.1 :011 > old.deep_merge(new) : new }
2.6.1 :012?> end
2.6.1 :013?> end
=> :deep_merge
2.6.1 :014 > h1 = {"a"=>{"x"=>"1","y"=>"2"}, "b"=>"z"}
=> {"a"=>{"x"=>"1", "y"=>"2"}, "b"=>"z"}
2.6.1 :015 > h2 = {"a"=>{"x"=>"3"}, "b"=>"q"}
=> {"a"=>{"x"=>"3"}, "b"=>"q"}
2.6.1 :016 > h1.deep_merge(h2)
=> {"a"=>{"x"=>"3", "y"=>"2"}, "b"=>"q"}
2.6.1 :017 >