如何基于相同的哈希键值合并两个哈希数组?

时间:2013-07-01 16:54:50

标签: ruby

所以我有两个哈希数组:

a = [{"b"=>123,"c"=>456}, {"b"=>456,"c"=>555}]
b = [{"c"=>456,"d"=>789},  {"b"=>222,"c"=>444}]

如何将ca中的键b的值相等的条件将它们连接起来?意思是我希望能够与a['c'] == b['c']

的条件连接起来

这是我想要得到的结果:

final_array = [{"b"=>123,"c"=>456,"d"=>789}, {"b"=>456,"c"=>555}, {"b"=>222,"c"=>444}]

3 个答案:

答案 0 :(得分:6)

a = [{"b"=>123,"c"=>456}, {"b"=>456,"c"=>555}]
b = [{"c"=>456,"d"=>789}, {"b"=>222,"c"=>444}]

p a.zip(b).map{|h1,h2| h1["c"] == h2["c"] ? h1.merge(h2) : [h1 ,h2]}.flatten
# => [{"b"=>123, "c"=>456, "d"=>789}, {"b"=>456, "c"=>555}, {"b"=>222, "c"=>444}]

答案 1 :(得分:3)

a = [{"b"=>123,"c"=>456}, {"b"=>456,"c"=>555}]
b = [{"c"=>456,"d"=>789},  {"b"=>222,"c"=>444}]

def merge_hashes_with_equal_values(array_of_hashes, key)
  array_of_hashes.sort { |a,b| a[key] <=> b[key] }.
    chunk { |h| h[key] }.
    each_with_object([]) { |h, result|  result << h.last.inject(&:merge) }
end

p merge_hashes_with_equal_values(a + b, 'c')

# => [{"b"=>222, "c"=>444}, {"c"=>456, "d"=>789, "b"=>123}, {"b"=>456, "c"=>555}]

首先连接数组,然后将其传递给方法,并使用哈希键进行组合。对该数组进行排序然后将散列放在另一个数组中彼此相邻合并,这使得合并更容易编程。在这里,我选择#chunk来处理连续运行哈希的检测,使用相同的键进行合并,并选择#each_with_object来编译最终的数组。

由于此方法需要处理一个数组,因此起始数组的长度不必相等,并且这些数组的顺序无关紧要。缺点是操作的键必须包含可排序的值(例如,没有nils)。

这是另一种解决问题的方法,这个方法使用哈希来构建结果:

def merge_hashes_with_equal_values(array_of_hashes, key)
  result = Hash.new { |h,k| h[k] = {} }
  remainder = []
  array_of_hashes.each_with_object(result) do |h, answer|
    if h.has_key?(key)
      answer[h.fetch(key)].merge!(h)
    else
      remainder << h
    end
  end.values + remainder
end

答案 2 :(得分:0)

Enumerable#flat_mapHash#update是实现此目的的完美方法:

a = [{"b"=>123,"c"=>456}, {"b"=>456,"c"=>555}]    
b = [{"c"=>456,"d"=>789}, {"b"=>222,"c"=>444}]
p a.zip(b).flat_map{|k,v| next k.update(v) if k["c"] == v["c"];[k,v]}
# >> [{"b"=>123, "c"=>456, "d"=>789}, {"b"=>456, "c"=>555}, {"b"=>222, "c"=>444}]