新手问题 求一简洁优美的写法

HKB · 2013年04月26日 · 最后由 chenge 回复于 2016年07月04日 · 3524 次阅读

现有两个 Array:

arr1 = [
{:key => 1, :b => 3}, 
{:key => 2, :b => 4}, 
{:key => 3, :b => 4}
]

arr2 = [
{:key => 1, :c => 4}, 
{:key => 2, :d => 5}
]

, 通过数组里每个 Hash 的:key去配对,结果保存到 arr1 里,最终想得到:

arr1 = [
{:key => 1, :b => 3, :c => 4}, 
{:key => 2, :b => 4, :d => 5}, 
{:key => 3, :b => 4}
]

下面是我的笨方法,求指点:

arr1.map! do |a|
  arr2.each do |b|
    if a[:key] == b[:key]
      a.merge!(b)
      break
    end
  end
  a
end

[1] pry(main)> (arr1 + arr2).group_by{|o| o[:key]}.map{|k, v| v.reduce(:merge!)}
=> [{:key=>1, :b=>3, :c=>4}, {:key=>2, :b=>4, :d=>5}, {:key=>3, :b=>4}]

其实还是你的比较快吧. 💨

有时候当你感觉处理起来比较麻烦时,有可能实际上是数据结构的问题。为什么不让:key 成为真正的 key 呢?

#2 楼 @yanhao 头像好像 Andrew Ng, = =

@Juven 太抬举敝人了。

@yanhao , 可以把 arr1 和 arr2 看成取自两个不同数据库的表中的部分数据,能跨数据库关联起来么?

@Saito , 数据不多的情况下这点差异应该可以忽略, 学习了group_byreduce 的用法, 谢了。

arr1.map!{|a| a.merge!(arr2.find{ |b| b[:key] == a[:key]} ||{}) }

#2 楼 @yanhao 还是觉得 2 楼的方向才是正道

如果 arr2 中有 arr1 不存在的 key,或者某个 key 重复出现,结果就有问题吧?还是说你本来就是想做 left join?O(n ^ 2) 的算法能不用尽量不用

arr1 = [
  {:key => 1, :b => 3},
  {:key => 2, :b => 4},
  {:key => 3, :b => 4},
]

arr2 = [
  {:key => 1, :c => 4},
  {:key => 2, :d => 5},
  {:key => 1, :foo => "foo"},
]

arr3 = [
  {:key => 4, :c => 3},
  {:key => 5, :c => 4},
]

result = Hash.new{|h, k| h[k] = {}}
[arr1, arr2, arr3].each do |arr|
  arr.each {|e| result[e[:key]].merge! e }
end
result = result.values

p result

@reus , 你说的这种情况, 在我这里是不会出现的。arr2 其实是根据 arr1 中的 key 得到的。所以 arr2 中不会有 arr1 不存在的 key,也不会重复。 @fsword , arr1 其实是从一个数据库的某张表取得的几条记录,根据其中的 keys,又从另一个数据库获得 arr2, 然后想把这几条记录根据 key 整合起来。

#10 楼 @HKB 那可以直接在数据库做 join

这样可以么? (arr1+arr2).group_by{|i| i[:key]}.collect{|k,v| v.inject(:merge)}

12 楼的代码神了

其实我想说 用通俗易懂的方法达到效果就行了

chenge Ruby 学习汇集,请推荐内容 提及了此话题。 07月04日 11:35
需要 登录 后方可回复, 如果你还没有账号请 注册新账号