Ruby. Merging a nested hash without overwriting

ⅰ亾dé卋堺 提交于 2019-12-10 11:00:15

问题


I have a nested hash:

{
  ["X", 1, 2, 3]=> {
    ["X", "O", 2, 3]=> {
      ["X", "O", "X", 3]=>["X", "O", "X", "O"]
    }
  }
}

I want to merge a given nested hash:

{
  ["X", 1, 2, 3]=> {
    ["X", "O", 2, 3]=> {
      ["X", "O", 2, "X"] => ["X", "O", "O", "X"]
    }
  }
}

such that:

{
  ["X", 1, 2, 3]=> {
    ["X", "O", 2, 3]=> {
      ["X", "O", "X", 3]=>["X", "O", "X", "O"],
      ["X", "O", 2, "X"] => ["X", "O", "O", "X"]
    }
  }
}

What's the best way?

The hashes I'll be merging will have an equivalent key at an arbitrary depth of nested-ness. The value of the last nested hash will always be different from all the other hashes.


回答1:


If you're sure that all the duplicate keys have values that are Hashes, you can use a recursive Hash#merge with block :

def deep_merge(h1,h2)
  h1.merge(h2){|k,v1,v2| deep_merge(v1,v2) }
end

With your example :

{["X", 1, 2, 3]=>
  {["X", "O", 2, 3]=>
    {["X", "O", "X", 3]=>["X", "O", "X", "O"],
     ["X", "O", 2, "X"]=>["X", "O", "O", "X"]}}}

NOTE: This method doesn't work in the general case, and shouldn't be used for anything else than the structure defined in the question. It will fail for deep_merge({a:1},{a:2}).

If you don't have information about the nested keys and values :

def deep_merge(h1,h2)
  h1.merge(h2){|k,v1,v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? deep_merge(v1,v2) : v2}
end

In case of a conflict with values that aren't both Hashes, the second value will overwrite the first one.

Both methods return a new hash, and do not modify either h1 or h2.

NOTE: This method is available in Rails.



来源:https://stackoverflow.com/questions/41109599/ruby-merging-a-nested-hash-without-overwriting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!