我有两个哈希数组,它们模拟数据库中的两个表,第一个哈希中的一个键引用第二个哈希中的单独命名的键,示例如下:
cars = [ { id: 1, color: 'red', owner_id: 1 }, { id: 2, color: 'black', owner_id: 1 } ]
owners = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]
我想尝试在这两个哈希上完成"连接",从而产生一个新的哈希数组,以便owners
的键和值将合并到任何cars
哈希中,其中汽车的:owner_id
与车主的:id
相匹配。所以在上面的示例中,结果将如下所示:
[ { id: 1, color: 'red', owner_id: 1, name: 'Alice' }, { id: 2, color: 'black', owner_id: 1, name: 'Alice' } ]
有人对我如何实现这一目标有任何想法吗?谢谢!
[编辑] 更新以澄清我希望将结果放置在新的哈希数组中,而不是改变任何一个原始数组。
def join(referers, referees, on_referer, on_referee)
referers.map do |record|
referees.find do |referee_record|
record[on_referer] == referee_record[on_referee]
end.merge(record)
end
end
cars = [ { id: 1, color: 'red', owner_id: 1 }, { id: 2, color: 'black', owner_id: 1 } ]
owners = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]
join(cars, owners, :owner_id, :id)
# => [{:id=>1, :name=>"Alice", :color=>"red", :owner_id=>1},
# {:id=>2, :name=>"Alice", :color=>"black", :owner_id=>1}]
编辑:我刚刚注意到,cars
中的关键:owner_id
要与owners
中的:id
相匹配。我以为汽车的关键:id
是匹配的。我将保持我的答案不变,考虑到修改是微不足道的,如果匹配是相同的键名,可能会更容易遵循。
假设:
- 你想修改(改变(
cars
;和 - 对于
owners
的每个元素h
都有一个cars
的元素g
,h[:id] == g[:id]
,
只是
owners.each { |h| cars.find { |g| g[:id] == h[:id] }.update(h) }
cars #=> [{:id=>1, :color=>"red", :owner_id=>1, :name=>"Alice"},
# {:id=>2, :color=>"black", :owner_id=>1, :name=>"Bob"}]
另一方面,如果:
- 您不希望
cars
或 - 对于
owners
h
的给定元素,可能没有h[:id]==g[:id]
或cars
的g
元素 - 你只是想提高效率,
您可以先为键值为 :id
的cars
或owners
创建哈希。
假设:
owners = [ { id: 3, name: 'Alice' }, { id: 2, name: 'Bob' } ]
我们可以为owners
创建一个哈希:
owners_by_id = owners.each_with_object({}) { |g,h| h.update(g[:id]=>g) }
#=> {3=>{:id=>3, :name=>"Alice"}, 2=>{:id=>2, :name=>"Bob"}}
然后写:
cars.map do |h|
g = {}.merge(h)
id = g[:id]
g.update(owners_by_id[id]) if owners_by_id.key?(id)
g
end
#=> [{:id=>1, :color=>"red", :owner_id=>1},
# {:id=>2, :color=>"black", :owner_id=>1, :name=>"Bob"}]
假设数组中相同位置的哈希对应于:
[cars, owners].transpose.map{|h1, h2| h1.merge(h2)}
否则,你的例子是不好的。