Ruby中哈希数组的选择性合并

时间:2015-08-15 09:13:17

标签: arrays ruby hash

我有两个包含哈希的数组:

a = [
  {:umc=>"11VE", :title=>"FOOBARS"},
  {:umc=>"1973", :title=>"ZOOBARS"},
  {:umc=>"1140", :title=>"TINYBAR"},
]

b = [
  {:umc=>"11VE", :code=>"23"},
  {:umc=>"10EE", :code=>"99"},
  {:umc=>"1140", :code=>"44"},
  {:umc=>"1973", :code=>"55"},
]

并希望有选择地将它们合并到具有哈希的另一个数组中,如下所示:

c = [
  {:umc=>"11VE", :title=>"FOOBARS", :code=>"23"},
  {:umc=>"1973", :title=>"ZOOBARS", :code=>"55"},
  {:umc=>"1140", :title=>"TINYBAR"} :code=>"44"},
]

我正在使用代码

combo=(a+b).group_by{|h| h[:umc]}.map{|k,v| v.reduce(:merge)}

合并两个数组就好了,但我希望结果只包含出现在第一个数组中的项目。

作为第二个想法,能够有两个结果是很棒的,一个包含从两个初始数组合并的项目,另一个包含第一个但不在第二个数据中的元素。

2 个答案:

答案 0 :(得分:2)

b.reduce(a) do |memo, e| 
  (ae = memo.detect { |ae| ae[:umc] == e[:umc] }) && ae.merge!(e)
  memo
end

Cary提出了“更具可读性”的表达合并方式,加上我们是否不想改变初始a数组,我们应该dup它的元素:

b.reduce(a.map(&:dup)) do |memo, e| 
  ae = memo.detect { |ae| ae[:umc] == e[:umc] }
  ae.merge!(e) if ae
  memo
end

答案 1 :(得分:0)

试试这个

# @a - Pivot array(elements that will be in result array)
# @b - Array which contains intersecting elements
# @group - attribute name, which identify similarity of elements
def c_join(a, b, group)
  result = []
  a.each do |a_i|
    similar = b.detect{ |b_i| b_i[group] == a_i[group] }
    result << a_i.merge(similar)
  end
  result
end

测试

a = [
  {:umc=>"11VE", :title=>"FOOBARS"},
  {:umc=>"1973", :title=>"ZOOBARS"},
  {:umc=>"1140", :title=>"TINYBAR"},
]

b = [
  {:umc=>"11VE", :code=>"23"},
  {:umc=>"10EE", :code=>"99"},
  {:umc=>"1140", :code=>"44"},
  {:umc=>"1973", :code=>"55"},
]

c_join(a, b, :umc)

结果

[
  {:umc=>"11VE", :title=>"FOOBARS", :code=>"23"}, 
  {:umc=>"1973", :title=>"ZOOBARS", :code=>"55"}, 
  {:umc=>"1140", :title=>"TINYBAR", :code=>"44"}
]