Merge hashes in array [ruby]
I have array of hashes
[{:id=>2, :price_psm=>450, :rooms_count=>3, :sq=>50, :tax_inc=>"t", :title=>"title1"},
{:id=>2, :price_psm=>499, :rooms_count=>3, :sq=>40, :tax_inc=>"t", :title=>"title1"},
{:id=>2, :price_psm=>499, :rooms_count=>3, :sq=>41, :tax_inc=>"t", :title=>"title1"},
{:id=>1, :price_psm=>450, :rooms_count=>2, :sq=>20, :tax_inc=>"t", :title=>"title2"}]
how i can merge identical hashes and create something like this:
[{:id=>2, :price_psm=>[450,499,499], :rooms_count=>3, :sq=>[50,40,41], :tax_inc=>"t", :title=>"title1"},
{:id=>1, :price_psm=>450开发者_StackOverflow中文版, :rooms_count=>2, :sq=>20, :tax_inc=>"t", :title=>"title2"}]
Something like:
require 'pp'
INPUT = [{:id=>2, :price_psm=>450, :rooms_count=>3, :sq=>50, :tax_inc=>"t", :title=>"title1"},
{:id=>2, :price_psm=>499, :rooms_count=>3, :sq=>40, :tax_inc=>"t", :title=>"title1"},
{:id=>2, :price_psm=>499, :rooms_count=>3, :sq=>41, :tax_inc=>"t", :title=>"title1"},
{:id=>1, :price_psm=>450, :rooms_count=>2, :sq=>20, :tax_inc=>"t", :title=>"title2"}]
RES = INPUT.group_by {|row| row[:id] }.collect do |k,v|
keys = v.collect {|rec| rec.keys}.flatten.uniq
group = {}
keys.each do |key|
vals = v.collect { |rec| rec[key] }.uniq.compact
group[key] = vals.size > 1 ? vals : vals.first
end
group
end
pp RES
Another functional approach (shorter)
hashes.reduce do |a, b|
a.merge(b) { |k, v1, v2| v1 == v2 ? v1 : [v1, v2].flatten }
end
#reduce
mashes everything down to a single value, #merge
merges Hash objects together, and can resolve merge conflicts with the block you provide.
EDIT | Whoops, sorry, misread the desired output. This one does that:
hashes.group_by { |hash| hash[:id] }.map do |id, hashes|
hashes.reduce do |a, b|
a.merge(b) { |key, v1, v2| v1 == v2 ? v1 : [v1, v2].flatten }
end
end
精彩评论