模拟Hashes之间的连接

时间:2015-08-28 21:36:08

标签: ruby

我有两个哈希数组,它们模拟数据库中的两个表,第一个哈希中的一个键引用第二个哈希中单独命名的键,例如:

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中的键和值将合并到任何{{1}中汽车“cars与所有者:owner_id匹配的哈希值。所以在上面的例子中,结果如下所示:

:id

任何人对我如何实现这一点有任何想法?谢谢!

[编辑]更新以澄清我希望将结果放在一个新的哈希数组中,而不是改变任何一个原始数组。

3 个答案:

答案 0 :(得分:3)

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}]

答案 1 :(得分:1)

修改:我刚刚注意到,:owner_id中的cars键与:id中的owners匹配。我假设汽车中的钥匙:id是匹配的。我将保留原样的答案,考虑到修改是微不足道的,如果匹配的名称相同,则可能更容易理解。

假设:

  • 你想修改(mutate)cars;和
  • 对于h的每个元素ownersg的元素carsh[: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
  • 对于h的给定元素ownersg
  • 可能没有cars的{​​{1}}元素
  • 你只是想提高效率,

您可以先为h[:id]==g[:id]cars创建一个哈希,其键值为owners

假设:

:id

我们可以为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"}} 

答案 2 :(得分:-1)

假设数组中相同位置的散列对应:

[cars, owners].transpose.map{|h1, h2| h1.merge(h2)}

否则,你的例子很糟糕。