Ruby: merging arrays or hashes
I'm having trouble understanding how to solve this issue, essentially I have two arrays that look like:
First array:
days_to_report
#=> [{:date=>Fri, 01 Apr 2011},
#=> {:date=>Sat, 02 Apr 2011},
#=> {:date=>Sun, 03 Apr 2011},
#=> {:date=>Mon, 04 Apr 2011}]
Second array:
tracks_by_day
#=> [{:date=>Mon, 04 Apr 2011, :count=>905, :perce开发者_C百科ntage=>13.205895228367137},
#=> {:date=>Sat, 02 Apr 2011, :count=>6745, :percentage=>98.4240478622501},
#=> {:date=>Fri, 01 Apr 2011, :count=>6853, :percentage=>100.0}]
The dates being Date
objects in this case.
So I want to like merge them so that for every item in the first array (days_to_report
), has the data that the second array has too, like the ideal output would be: (notice the data for the date for Sun, 03 Apt 2011)
[{:date=>Mon, 04 Apr 2011, :count=>905, :percentage=>13.205895228367137},
{:date=>Sun, 03 Apr 2011, :count=>0, :percentage=>0},
{:date=>Sat, 02 Apr 2011, :count=>6745, :percentage=>98.4240478622501},
{:date=>Fri, 01 Apr 2011, :count=>6853, :percentage=>100.0}]
Notice that the second item of the array has zero for the values because the :date
wasn't in the hash for the tracks_by_day
array... any thoughts on how to accomplish this? It seems like the functionality provided in zip
or something, but I need to match up the keys to see if they exist and zero fill their values if they don't.
I hope I'm describing this correctly, thanks again guys! high five!
days = days_to_report.map{|d| d[:date] } - tracks_by_day.map{|d| d[:date]}
days.each{ |d| tracks_by_day << {:date => d, :count => 0, :percentage => 0} }
OR
days.inject(tracks_by_day){|a,d| a << {:date => d, :count => 0, :percentage => 0}}
This is how I would do it as long as there's not a huge number of items:
days_to_report.each do |day_hash|
tracks = tracks_by_day.find {|h| h[:date] == day_hash[:date]}
day_hash.merge!(tracks || {:count=>0, :percentage=>0})
end
If tracks_by_day
is huge, you might want to convert it to a hash first that maps dates to their data.
Try this:
idx = tracks_by_day.index_by {|r| r.first }
days_to_report.map do |r|
data = (idx[r.first] || []).first || {:count=>0, :percentage=>0}
r.merge(data)
end
(days_to_report+tracks_by_day).group_by {|h| h[:date]}.
map{|date, (h1, h2)| {:count => 0, :percentage => 0}.merge(h1).merge(h2 || {})}
精彩评论