How to combine a hash array based on the same keys in a ruby?

how to combine an array of hashes based on the same keys in ruby?

example:

a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}] 

How to get such a result?

 a = [{:a=>[1, 10]},{:b=>8},{:c=>[7, 2]}] 

thanks before

+6
source share
4 answers

Try

 a.flat_map(&:entries) .group_by(&:first) .map{|k,v| Hash[k, v.map(&:last)]} 
+7
source

Another alternative:

 a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}] p a.each_with_object({}) { |h, o| h.each { |k,v| (o[k] ||= []) << v } } # => {:a=>[1, 10], :b=>[8], :c=>[7, 2]} 

It also works when hashes have several key / value combinations, for example:

 b = [{:a=>1, :b=>5, :x=>10},{:a=>10, :y=>2},{:b=>8},{:c=>7},{:c=>2}] p b.each_with_object({}) { |h, o| h.each { |k,v| (o[k] ||= []) << v } } # => {:a=>[1, 10], :b=>[5, 8], :x=>[10], :y=>[2], :c=>[7, 2]} 
+4
source

A minor addition to Ari Shaw's answer to match the required answer:

 a.flat_map(&:entries) .group_by(&:first) .map{|k,v| Hash[k, v.size.eql?(1) ? v.last.last : v.map(&:last) ]} #=> [{:a=>[1, 10]}, {:b=>8}, {:c=>[7, 2]}] 
+3
source

I would do:

 a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}] merged_hash = a.each_with_object({}) do |item,hsh| k,v = item.shift hsh[k] = hsh.has_key?(k) ? [ *Array( v ), hsh[k] ] : v end merged_hash.map { |k,v| { k => v } } # => [{:a=>[10, 1]}, {:b=>8}, {:c=>[2, 7]}] 

Update

The best taste:

 a = [{:a=>1},{:a=>10},{:b=>8},{:c=>7},{:c=>2}] merged_hash = a.each_with_object({}) do |item,hsh| k,v = item.shift (hsh[k] ||= []) << v end merged_hash.map { |k,v| { k => v } } # => [{:a=>[10, 1]}, {:b=>8}, {:c=>[2, 7]}] 
+1
source

All Articles