【问题标题】:Merge nested hash without overwritting in Ruby在 Ruby 中合并嵌套哈希而不覆盖
【发布时间】:2015-11-22 23:29:37
【问题描述】:

检查此Ruby convert array to nested hash 和其他网站后,我无法实现以下转换:

我有这个:

{"a"=>"text"}
{"b"=>{"x"=>"hola"}}
{"b"=>{"y"=>"pto"}

}

我想获得:

{"a"=>text,
    b=>{"x" => "hola",
        "y" => "pto"    
    }
}

到目前为止,代码看起来是这样的:

tm =[[["a"],"text"],[["b","x"],"hola"],[["b","y"],"pto"]]

q = {}
tm.each do |l|
    q = l[0].reverse.inject(l[1]) { |p, n| { n => p } }
    i += 1

end

我尝试使用merge,但它会覆盖键!我也试过这个How can I merge two hashes without overwritten duplicate keys in Ruby?,但它一直在覆盖。

更新:

如何为未定义的嵌套哈希(级别)执行此操作? hash[key1][key2][key3]... = "value"

{"a"=>"text"},
    {"b"=>{"x"=>"hola"},
    {"b"=>{"y"=>"pto"},
    {"c"=>{"g"=>{"k" => "test1"}},
    ...
}

【问题讨论】:

标签: arrays ruby hash


【解决方案1】:

您可以使用 merge 和块来告诉 Ruby 如何处理重复键:

a = {"a"=>"text"}
b = {"b"=>{"x"=>"hola"}}
c = {"b"=>{"y"=>"pto"}}

a.merge(b).merge(c) { |key, left, right| left.merge(right) }
#=> {"a"=>"text", "b"=>{"x"=>"hola", "y"=>"pto"}}

【讨论】:

  • 这很好用,但我忘了说我需要这个用于未定义的嵌套级别。这适用于最多 2 个级别。我更新了我的问题。
【解决方案2】:

对于 Rails,ActiveSupportdeep_merge 函数可以满足您的要求。

你可以自己实现如下:

class ::Hash
    def deep_merge(second)
        merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
        self.merge(second, &merger)
    end
end

现在,

h1 = {"a"=>"text"}
h2 = {"b"=>{"x"=>"hola"}}
h3 = {"b"=>{"y"=>"pto"}}
h1.deep_merge(h2).deep_merge(h3)
# => {"a"=>"text", "b"=>{"x"=>"hola", "y"=>"pto"}}

【讨论】:

  • 使用 deep_merge 以递归方式顺利工作。谢谢
猜你喜欢
  • 2017-04-27
  • 2019-02-21
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 2019-11-21
  • 1970-01-01
相关资源
最近更新 更多