在Ruby中,在值匹配的地方合并多个哈希数组



我有3个带有多个散列的数组,我正试图将它们转换为一个散列数组,其中键/值与匹配

a = [{"name"=>"aaa", "a"=>"1", "b"=>"2"}, {"name"=>"bbb", "a"=>"1", "b"=>"2"}]
b = [{"name"=>"aaa", "c"=>"1", "d"=>"2"}, {"name"=>"bbb", "c"=>"1", "d"=>"2"}]
c = [{"name"=>"aaa", "e"=>"1", "f"=>"2"}, {"name"=>"bbb", "e"=>"1", "f"=>"2"}]

获取

combined = [{"name"=>"aaa", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}, {"name"=>"bbb", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}]

我认为这正是您所需要的。

hashes = [a, b, c]
result = hashes.inject([]) do |result, hash_array|
hash_array.each do |hash|
index = result.find_index{|item| item["name"] == hash["name"]}
if index
result[index] = result[index].merge(hash)
else
result << hash
end
end
result
end

这看起来更酷,应该也能解决您的问题:

a.zip(b,c).map{|vertical_array| e.inject({}) {|result, k| result.merge(k)} }

控制台:

2.5.1 :016 > a.zip(b,c).map{|e|e.inject({}){|result, k| result.merge(k)} }
=> [{"name"=>"aaa", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}, {"name"=>"bbb", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}] 
[a,b,c].transpose
.map { |arr| arr.reduce(&:merge) }
#=> [{"name"=>"aaa", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"},
{"name"=>"bbb", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}]

如果不能保证abc的元素的顺序,则可以写入

[a,b,c].map { |arr| arr.sort_by { |h| h["name"] } }
.transpose
.map { |arr| arr.reduce(&:merge) }

(a+b+c).each_with_object({}) do |g,h|
h.update(g["name"]=>g) { |_,o,n| o.merge(n) }
end.values

后者使用散列#更新(又名merge!(的形式,该散列#更新采用块({ |_,o,n| o.merge(n) }(来确定在被合并的两个散列中存在的密钥的值。请注意,这里Hash#值的接收器是

(a+b+c).each_with_object({}) do |g,h|
h.update(g["name"]=>g) { |_,o,n| o.merge(n) }
end
#=> {"aaa"=>{"name"=>"aaa", "a"=>"1", "b"=>"2", "c"=>"1",
#            "d"=>"2", "e"=>"1", "f"=>"2"},
#    "bbb"=>{"name"=>"bbb", "a"=>"1", "b"=>"2", "c"=>"1",
#            "d"=>"2", "e"=>"1", "f"=>"2"}]

这种计算还允许数据内容的更大变化。例如,假设:

a = [{"name"=>"aaa", "a"=>"1", "b"=>"2"}, {"name"=>"bbb", "a"=>"1", "b"=>"2"}]
b = [{"name"=>"bbb", "c"=>"1", "d"=>"2"}, {"name"=>"ccc", "c"=>"1", "d"=>"2"}]
c = [{"name"=>"ccc", "e"=>"1", "f"=>"2"}, {"name"=>"aaa", "e"=>"1", "f"=>"2"}]

然后

(a+b+c).each_with_object({}) do |g,h|
h.update(g["name"]=>g) { |_,o,n| o.merge(n) }
end
#=> {"aaa"=>{"name"=>"aaa", "a"=>"1", "b"=>"2", "e"=>"1", "f"=>"2"},
#    "bbb"=>{"name"=>"bbb", "a"=>"1", "b"=>"2", "c"=>"1", "d"=>"2"},
#    "ccc"=>{"name"=>"bbb", "c"=>"1", "d"=>"2", "e"=>"1", "f"=>"2"}]

最新更新