先写几个方法。
class Hash def deep_merge(hash) target = dup hash.keys.each do |key| if hash[key].is_a? Hash and self[key].is_a? Hash target[key] = target[key].deep_merge(hash[key]) next end target[key] = hash[key] end target end def deep_merge!(second) second.each_pair do |k, v| if self[k].is_a?(Hash) and second[k].is_a?(Hash) self[k].deep_merge!(second[k]) else self[k] = second[k] end end end def deep_merge2(other) deep_proc = Proc.new { |k, s, o| if s.kind_of?(Hash) && o.kind_of?(Hash) next s.merge(o, &deep_proc) end next o } merge(other, &deep_proc) end def deep_merge3(second) merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 } self.merge(second, &merger) end def keep_merge(hash) target = dup hash.keys.each do |key| if hash[key].is_a? Hash and self[key].is_a? Hash target[key] = target[key].keep_merge(hash[key]) next end target.update(hash) { |key, *values| values.flatten.uniq } end target end end
示例:
h1 = {:a => {:b => :c}} h2 = {:a => {:l => :x}} m1 = h1.merge(h2) m2 = h1.deep_merge(h2) m3 = h1.deep_merge2(h2) m4 = h1.deep_merge!(h2) m5 = h1.deep_merge3(h2) p m1 #=> {:a=>{:l=>:x}} p m2 #=> {:a=>{:l=>:x, :b=>:c}} p m3 # => {:a=>{:l=>:x, :b=>:c}} p m4 # => {:a=>{:l=>:x}} p m5 # => {:a=>{:l=>:x, :b=>:c}} first = { :data => { :name => { :first => 'Sam', :middle => 'I', :last => 'am' } } } second = { :data => { :name => { :middle => 'you', :last => 'are' } } } p first.deep_merge3(second) # => {:data=>{:name=>{:first=>"Sam", :last=>"are", :middle=>"you"}}} p first.keep_merge(second) # => {:data=>{:name=>{:first=>"Sam", :last=>["am", "are"], :middle=>["I", "you"]}}}