您可以按如下方式执行此操作:
sql1 = [{id1: 1, name: 'john', role: 'user'},{id1: 2, name: 'matt', role: 'admin'}]
sql2 = [{id2: 4, externalName: 'john'},{id2: 8, externalName: 'ronald'}]
[*sql1,*sql2]
.group_by { |h| h[:name] || h[:externalName] }
.flat_map do |k,v|
v.reduce(&:merge).tap { |h| h.delete(:externalName) if h.key?(:name) }
end
#=> => [{:id1=>1, :name=>"john", :role=>"user", :id2=>4}, {:id1=>2, :name=>"matt", :role=>"admin"}, {:id1=>17, :role=>"user"}, {:id2=>8, :externalName=>"ronald"}]
步骤:
[*sql1,*sql2]
-合并两个数组
.group_by {|h| h[:name] || h[:externalName]}
-如果h[:name]
为假,则按值:name
或:externalName
对元素进行分组(在本例中假定为nil
)
map do |_,v|
-将根据块的返回值返回一个新的数组,当在Hash
上调用(由group_by
返回)时,它将为块产生键和值.在这种情况下,我们不关心密钥,所以我们使用_
来表示这一点.
v.reduce(&:merge)
-将值合并为单个Hash
tap { |h| h.delete(:externalName) if h.key?(:name) }
-tap
将结果Hash
产生给块,并且如果Hash
具有name
密钥,则我们删除:externalName
密钥.此块将始终返回生成的对象.
Update
显然,name
不是必需的键,这导致了一个由nil
个值组成的大组,其中合并缩减不是一个选项.更新了处理nil
分组的代码.
sql1 = [{id1: 1, name: 'john', role: 'user'},{id1: 2, name: 'matt', role: 'admin'}, {id1: 17, role: 'user'}, {id1: 12, role: 'admin'} ]
sql2 = [{id2: 4, externalName: 'john'},{id2: 8, externalName: 'ronald'}, {id2: 42}]
[*sql1,*sql2]
.group_by { |h| h[:name] || h[:externalName] }
.flat_map do |k,v|
next v unless k
v.reduce(&:merge).tap { |h| h.delete(:externalName) if h.key?(:name) }
end
#=> [{:id1=>1, :name=>"john", :role=>"user", :id2=>4}, {:id1=>2, :name=>"matt", :role=>"admin"}, {:id1=>17, :role=>"user"}, {:id1=>12, :role=>"admin"}, {:id2=>42}, {:id2=>8, :externalName=>"ronald"}]
Other Assumptions个
以下是基于员额的假设:
sql1
中没有重复的名称或sql2
中没有重复的externalNames
(导致最大组为2;sql1
中值为1,sql2
中值为1)
- 在
sql1
和sql2
之间没有重叠的关键点.否则,结果值将为sql2