您可以如下修改您的代码:
bb = b.select { |f| a.any? { |h| h[:umc] == f[:umc] } }
#=> [{:umc=>"11VE", :code=>"23"},
# {:umc=>"1140", :code=>"44"},
# {:umc=>"1973", :code=>"55"}]
(a + bb).group_by { |g| g[:umc] }.map { |_,v| v.reduce(:merge) }
#=> [{:umc=>"11VE", :title=>"FOOBARS", :code=>"23"},
# {:umc=>"1973", :title=>"ZOOBARS", :code=>"55"},
# {:umc=>"1140", :title=>"TINYBAR", :code=>"44"}]
但这样计算bb 会更有效:
require 'set'
umc_a_vals = a.map { |g| g[:umc] }.to_set
#=> #<Set: {"11VE", "1973", "1140"}>
bb = b.select { |f| umc_a_vals.include(f[:umc]) }
#=> [{:umc=>"11VE", :code=>"23"},
# {:umc=>"1140", :code=>"44"},
# {:umc=>"1973", :code=>"55"}]
这是另一种方式:
f = a.group_by { |g| g }.map { |_,v| v.reduce(:merge) }
#=> [{:umc=>"11VE", :title=>"FOOBARS"},
# {:umc=>"1973", :title=>"ZOOBARS"},
# {:umc=>"1140", :title=>"TINYBAR"}]
b.each_with_object(f) do |g,h|
(h.update(g[:umc]=>g) { |_,o,n| o.merge(n) }) if h.key?(g[:umc])
end.values
#=> [{:umc=>"11VE", :title=>"FOOBARS", :code=>"23"},
# {:umc=>"1973", :title=>"ZOOBARS", :code=>"55"},
# {:umc=>"1140", :title=>"TINYBAR", :code=>"44"}]
f 的计算与你的代码非常相似,我认为不需要解释。
我们现在合并哈希:
{ g[:umc]=g }
#=> { "11VE"=>{:umc=>"11VE", :code=>"23"} }
如果h 有一个密钥"11VE",则进入h,它确实如此。为此,我们使用Hash#update(又名merge!)的形式,它使用了块:
{ |_,o,n| o.merge(n) }
确定在被合并的两个哈希中存在的键的值。
块变量相等:
_ #=> "11VE"
o #=> {:umc=>"11VE", :title=>"FOOBARS"}
n #=> {:umc=>"11VE", :code=>"23"}
所以分块计算的结果是:
o.merge(n)
#=> {:umc=>"11VE", :title=>"FOOBAR, :code=>"23"}
这是h[:umc]的更新值。
顺便说一句:我使用局部变量_ 作为键的值,以提醒人们注意它没有用于块计算。变量o 和n 通常分别用于表示“旧”和“新”值。
从b 的剩余值构造的散列合并到h 的过程类似。
最后一步是提取h的值。
作为第二个例子,假设:
a = [
{:umc=>"11VE", :title=>"FOOBARS"},
{:umc=>"11VE", :title=>"ZOOBARS", :author=>"Billy-Bob"},
{:umc=>"1140", :title=>"TINYBAR"}
]
我们得到:
f = a.each_with_object({}) { |g,h| h.update(g[:umc]=>g) { |_,o,n| o.merge(n) } }
#=> {"11VE"=>{:umc=>"11VE", :title=>"ZOOBARS", :author=>"Billy-Bob"},
# "1140"=>{:umc=>"1140", :title=>"TINYBAR"}}
b.each_with_object(f) do |g,h|
(h.update(g[:umc]=>g) { |_,o,n| o.merge(n) }) if h.key?(g[:umc])
end.values
#=> [{:umc=>"11VE", :title=>"ZOOBARS", :author=>"Billy-Bob", :code=>"23"},
# {:umc=>"1140", :title=>"TINYBAR", :code=>"44"}]