简体   繁体   中英

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, :percentage=>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 || {})}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM