红宝石。合并嵌套哈希而不覆盖

时间:2016-12-12 21:07:50

标签: ruby hash merge nested

我有一个嵌套哈希:

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

我想合并给定的嵌套哈希:

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

这样:

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

最好的方法是什么?

我将要合并的哈希值将在嵌套的任意深度处具有等效键。最后一个嵌套哈希的值总是与所有其他哈希值不同。

1 个答案:

答案 0 :(得分:2)

如果您确定所有重复键都具有哈希值,则可以使用带有块的递归Hash#merge

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

用你的例子:

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

注意:此方法在一般情况下不起作用,不应用于问题中定义的结构以外的任何其他方法。 deep_merge({a:1},{a:2})会失败。

如果您没有关于嵌套键和值的信息:

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

如果与不是两个哈希值的值发生冲突,则第二个值将覆盖第一个值。

两种方法都返回一个新的哈希值,不要修改h1或h2。

注意:此方法可在Rails中找到。

相关问题