【问题标题】:Ruby. Merging a nested hash without overwriting红宝石。合并嵌套哈希而不覆盖
【发布时间】:2017-04-27 20:02:43
【问题描述】:

我有一个嵌套哈希:

{
  ["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"]
    }
  }
}

最好的方法是什么?

我将要合并的散列将在任意嵌套深度处具有等效键。最后一个嵌套散列的值将始终与所有其他散列不同。

【问题讨论】:

  • 欢迎来到 Stack Overflow。请阅读“How to Ask”、“minimal reproducible example”和meta.stackoverflow.com/questions/261592/…。如果没有您尝试过的示例,您似乎希望我们为您编写代码,而不是解决您的代码问题。
  • 你不想看到我尝试了什么。
  • @Adzz:即使没有运行,即使它很漂亮,看到你尝试了一些东西,以及你是如何尝试的,仍然很高兴。
  • 是的,我们确实希望看到它。这就是我们为您提供最佳帮助的方式。

标签: ruby hash merge nested


【解决方案1】:

如果您确定所有重复键的值都是哈希值,则可以使用带有块的递归 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 中可用。

【讨论】:

  • 假设h1 = { a: { b: :c, d: :e } }; h2 = { a: { b: :c, f: :g } }。这不应该产生{ a: { b: :c, d: :e, b: :c, f: :g } }吗?您的代码 #1 引发了异常。
  • 第一种方法使用来自 OP 的信息The value of the last nested hash will always be different from all the other hashes.。您的示例没有满足此属性,因此第二种方法是您想要的方法。正如预期的那样,它返回{:a=>{:b=>:c, :d=>:e, :f=>:g}}
猜你喜欢
  • 2012-12-19
  • 1970-01-01
  • 2015-11-22
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多