我有两个哈希数组:
a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" }, ...]
a2 = [{ ID: 12496, name: "Robert", ORDER_NO: 5511426 }, ...]
我想在a2
中找到其ID
和name
字段与{{1}中某个条目的ID
和name
字段匹配的哈希值(不关心a1
或任何其他进入email
的项目),然后将a2
的值合并到这些值的ORDER_NO
哈希中。即结束:
a1
此外,我想忽略a2中存在但不存在于a1中的元素。
我正在做以下事情:
[{ ID: 12496, name: "Robert", email: "robert@example.com", ORDER_NO: 5511426 } ...]
但有更快的方法吗?
答案 0 :(得分:2)
使用Ruby的一些内置方法可以非常干净地完成。
a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" },
{ ID: 12497, name: "Lola", email: "lola@hotmail.com" },
{ ID: 12498, name: "Hank", email: "hank@hotmail.com" }]
a2 = [{ ID: 12497, name: "Lola", ORDER_NO: 5511427 },
{ ID: 12496, name: "Robert", ORDER_NO: 5511426 }]
index = a2.group_by{|entry| [entry[:ID], entry[:name]] }
a1.map{|entry| (index[[entry[:ID], entry[:name]]] || []).reduce(entry, :merge) }
结果:
[{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com", :ORDER_NO=>5511426},
{:ID=>12497, :name=>"Lola", :email=>"lola@hotmail.com", :ORDER_NO=>5511427},
{:ID=>12498, :name=>"Hank", :email=>"hank@hotmail.com"}]
故障:
首先,我们使用group_by
来构建a2中的条目表,这些表可能会合并到a1中的条目中。我们在id和name键上对此表进行索引,因为这些是我们用来确定哪些条目匹配的因素:
index = a2.group_by{|entry| [entry[:ID], entry[:name]] }
这会产生结果:
{[12497, "Lola"]=>[{:ID=>12497, :name=>"Lola", :ORDER_NO=>5511427}],
[12496, "Robert"]=>[{:ID=>12496, :name=>"Robert", :ORDER_NO=>5511426}]}
接下来,我们a1
将a1.map{|entry|
# ...
}
中的每个条目添加到其新表单中,并合并索引中的订单号:
a2
要获取我们将每个条目映射到的值,我们首先获取一个数组,其中包含a1
中适合与(index[[entry[:ID], entry[:name]]] || [])
中此条目合并的所有值:
[{:ID=>12497, :name=>"Lola", :ORDER_NO=>5511427}]
对于Lola,这将返回类似a2
的内容,为a1
中没有匹配条目的Hank返回一个空数组。
然后,从reduce(entry, :merge)
的条目开始,我们map
使用reduce
(例如{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com", :ORDER_NO=>5511426}
)从索引到一个哈希的所有条目,这导致像{{1}}这样的条目。
如果你不熟悉Ruby核心库中的方法,那么这一切看起来有点复杂。但是一旦你理解了简单的函数式编程概念,比如map和reduce,那么提出这样简单而强大的解决方案并不是那么困难。
答案 1 :(得分:1)
假设:
a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" },
{ ID: 12497, name: "Lola", email: "lola@hotmail.com" },
{ ID: 12498, name: "Hank", email: "hank@hotmail.com" }]
a2 = [{ ID: 12497, name: "Lola", ORDER_NO: 5511427 },
{ ID: 12496, name: "Robert", ORDER_NO: 5511426 }]
我建议你先构建哈希:
h2 = a2.each_with_object({}) { |g,h| h[[g[:ID], g[:name]]]=g[:ORDER_NO] }
#=> { [12497, "Lola"]=>5511427, [12496, "Robert"]=>5511426 }
然后只需单步执行a1
的元素,在适当的位置添加键值对:
a1.each do |g|
k = [g[:ID],g[:name]]
g[:ORDER_NO] = h2[k] if h2.key?(k)
end
a1
#=> [{ID: 12496, name: "Robert", email: "robert@hotmail.com", ORDER_NO: 5511426},
# {ID: 12497, name: "Lola", email: "lola@hotmail.com", ORDER_NO: 5511427},
# {ID: 12498, name: "Hank", email: "hank@hotmail.com"}]
我假设:
a1
中没有两个元素(哈希)对ID
和:name
具有相同的值; a2
中没有两个元素(哈希)对ID
和:name
具有相同的值;和a1
应该是muated。答案 2 :(得分:0)
你可以通过在合并之前将请求的属性放入散列中来更快地完成它,然后获取值(当然有假设是输入中值的唯一性)。
x1 = a1.reduce({}){|m, h| m[h.select{|k| [:ID, :name].include? k}] = h;m}
x2 = a2.reduce({}){|m, h| m[h.select{|k| [:ID, :name].include? k}] = h;m}
x1.merge(x2.select{|k,v| x1.key?(k)}){|k,o,n| o.merge(n)}.values
使用您的示例数据运行:
a1 = [{ ID: 12496, name: "Robert", email: "robert@hotmail.com" }]
=> [{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com"}]
a2 = [{ ID: 12496, name: "Robert", ORDER_NO: 5511426 }]
=> [{:ID=>12496, :name=>"Robert", :ORDER_NO=>5511426}]
x1 = a1.reduce({}){|m, h| m[h.select{|k| [:ID, :name].include? k}] = h;m}
=> {{:ID=>12496, :name=>"Robert"}=>{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com"}}
x2 = a2.reduce({}){|m, h| m[h.select{|k| [:ID, :name].include? k}] = h;m}
=> {{:ID=>12496, :name=>"Robert"}=>{:ID=>12496, :name=>"Robert", :ORDER_NO=>5511426}}
x1.merge(x2.select{|k,v| x1.key?(k)}){|k,o,n| o.merge(n)}.values
=> [{:ID=>12496, :name=>"Robert", :email=>"robert@hotmail.com", :ORDER_NO=>5511426}]