合并两个哈希并返回公共数据

时间:2015-03-20 09:51:15

标签: ruby hash

我有两个哈希:

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }

我需要返回哈希,例如:

h3 = { 
  "a" => { "h1" => 100, "h2" => nil},
  "b" => { "h1" => 200, "h2" => 254},
  "c" => { "h1" => nil, "h2" => 300}
}

我正在尝试使用:

h1.merge(h2) { |k, val, old| { 'h1' => val, 'h2' => old } }

但它只返回:

{"a"=>100, "b"=>{"h1"=>200, "h2"=>254}, "c"=>300}

没有。 有什么想法吗?

3 个答案:

答案 0 :(得分:3)

仅对重复键调用该块。您可以确保两个哈希都包含所有键:

h1 = { "a" => 100, "b" => 200, "c" => nil }
h2 = { "a" => nil, "b" => 254, "c" => 300 }

h1.merge(h2) { |k, val, old| { 'h1' => val, 'h2' => old } }
#=> {"a"=>{"h1"=>100, "h2"=>nil},
#    "b"=>{"h1"=>200, "h2"=>254},
#    "c"=>{"h1"=>nil, "h2"=>300}}

或者自己构建一个新哈希,例如使用两个哈希的键:

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }

(h1.keys | h2.keys).map { |k| [k, { 'h1' => h1[k], 'h2' => h2[k] }] }.to_h
#=> {"a"=>{"h1"=>100, "h2"=>nil},
#    "b"=>{"h1"=>200, "h2"=>254},
#    "c"=>{"h1"=>nil, "h2"=>300}}

答案 1 :(得分:2)

如果您阅读了mergehere)的官方文档,请说:

  

通过调用块确定每个重复键的值   使用键,其值在hsh中,其值在other_hash中。

这意味着对于密钥"a""c",永远不会调用该块(因为它们不是重复键),因此您在结果哈希中缺少nil。< / p>

你可以试试这个:

h3 = {}
(h1.keys + h2.keys).uniq.each{|a| h3[a] = {"h1" => h1[a], "h2" => h2[a]}}
h3
# => {"a"=>{"h1"=>100, "h2"=>nil}, "b"=>{"h1"=>200, "h2"=>254}, "c"=>{"h1"=>nil, "h2"=>300}}

答案 2 :(得分:1)

这是另一种在哈希和哈希标签数量方面有点笼统的方法:

h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h3 = { "c" => 111, "b" => 222 }
a = [h1,h2,h3]
labels = {h1=>"h1", h2=>"h2", h3=>"h3"}

h.reduce([]) { |keys,h| keys | h.keys }
 .each_with_object({}) { |k,h|
   h[k] = a.each_with_object({}) { |f,g| g[labels[f]] = f[k] } }
  #=> {"a"=>{"h1"=>100, "h2"=>nil, "h3"=>nil},
  #    "b"=>{"h1"=>200, "h2"=>254, "h3"=>222},
  #    "c"=>{"h1"=>nil, "h2"=>300, "h3"=>111}} 

步骤:

keys = h.reduce([]) { |keys,h| keys | h.keys }
  #=> ["a", "b", "c"]
enum = keys.each_with_object({})
  #=> #<Enumerator: ["a", "b", "c"]:each_with_object({})> 
k,h = enum.next
  #=> ["a", {}] 
h[k] = a.each_with_object({}) { |f,g| g[labels[f]] = f[k] }
  #=> {"h1"=>100, "h2"=>nil, "h3"=>nil} 
k,h = enum.next
  #=> ["b", {"a"=>{"h1"=>100, "h2"=>nil, "h3"=>nil}}] 
h[k] = a.each_with_object({}) { |f,g| g[labels[f]] = f[k] }
  #=> {"h1"=>200, "h2"=>254, "h3"=>222} 
k,h = enum.next
  #=> ["c", {"a"=>{"h1"=>100, "h2"=>nil, "h3"=>nil},
  #    "b"=>{"h1"=>200, "h2"=>254, "h3"=>222}}] 
h[k] = a.each_with_object({}) { |f,g| g[labels[f]] = f[k] }
  #=> {"h1"=>nil, "h2"=>300, "h3"=>111} 
h
  #=> {"a"=>{"h1"=>100, "h2"=>nil, "h3"=>nil},
  #    "b"=>{"h1"=>200, "h2"=>254, "h3"=>222},
  #    "c"=>{"h1"=>nil, "h2"=>300, "h3"=>111}}