【问题标题】:Ruby: how to perform "left join" on two arrays of hashes efficientlyRuby:如何有效地对两个哈希数组执行“左连接”
【发布时间】:2017-07-16 01:53:05
【问题描述】:

我正在尝试左加入以下哈希数组:

input:
a = [{id: 1, name: 'Bob'}, {id: 2, name: 'Jack'}, {id: 3, name: 'Tom'}]
b = [{id: 3, age: 12}, {id: 2, age: 7}]
output:
[{id: 1, name: 'Bob', age: nil}, {id: 2, name: 'Jack', age: 7}, {id: 3, name: 'Tom', age: 12}] 

目前我正在做一些事情:

a.map do |x|
  {
   id:   x[:id], 
   name: x[:name], 
   age:  (b.detect{|y| x[:id] == y[:id]} || {age: nil}).fetch(:age)
  }
end

可以,但是数据量大的时候超级慢。

有没有更好的方法来更高效地执行“加入”操作?

【问题讨论】:

  • 把左边的散列数组变成以:id为键的散列散列,这样你就有了{1 => {id: 1, name: 'Bob'}, 2 => {id: 2, name: 'Jack'}, …}
  • @CarySwoveland 你是对的。固定!

标签: ruby-on-rails arrays ruby algorithm hash


【解决方案1】:
[a, b].map { |a| a.group_by { |e| e[:id] } }
      .reduce do |a, b|
          a.merge(b) { |_, v1, v2| v1.first.merge v2.first }
        end.values
      .map do |e|
         Array === e ? {age:nil, name:nil}.merge(e.first) : e
      end

整个准备步骤需要O(N),然后合并以O(N) 完成,最后完成需要O(N)

【讨论】:

    【解决方案2】:
    h = b.each_with_object({}) { |g,h| h[g[:id]] = g[:age] }
      #=> {3=>12, 2=>7} 
    a.map { |g| g.merge(age: h[g[:id]]) }
      #=> [{:id=>1, :name=>"Bob",  :age=>nil},
      #    {:id=>2, :name=>"Jack", :age=>7},
      #    {:id=>3, :name=>"Tom",  :age=>12}] 
    

    如果a要原地修改,则将第二行改为

    a.each { |g| g[:age] = h[g[:id]] }
    
    a #=> [{:id=>1, :name=>"Bob",  :age=>nil},
      #    {:id=>2, :name=>"Jack", :age=>7},
      #    {:id=>3, :name=>"Tom",  :age=>12}] 
    

    【讨论】:

    • 这绝对比我的更红;由于我幸运地在几个月前退出了 Ruby 开发,我似乎失去了 90% 的视力 :)
    • @mudasobwa,您是否正在学习另一种语言、改变职业或退休?稍后将删除此评论。
    • 我爱上了Elixir。我曾经换过一个职业来写文案(除了大学时期的海军和劳工经验),我很确定我会永远从事编程工作。
    • @mudasobwa 我从 2011 年起就住在克拉科夫,2014 年我参加了 Jose 的演讲,他在那里谈到了 Elixir,那时我正处于编程生涯的起步阶段并且不明白他所说的很多(几乎没有),但他这样做的方式让我相信,这种语言是未来。很酷,你已经切换到它!
    • @AndreyDeineko 是的,何塞喜欢他所做的事情,这也是他做得很好的一个要点。此外,他还是一位出色的软件工程师。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 2016-02-27
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    相关资源
    最近更新 更多