There is rarely just one way to do a calculation in Ruby, and this is no exception. Here's another way. Note that I've allowed for the possibility that two or more movies are showing on the same day.
Code
def aggregate_by_date(dates, movies)
movies.each_index.with_object({}) { |i,h| (h[dates[i]] ||= []) << movies[i] }
end
Example
movies = [
{:movie=>"The Neon Demon", :time=>"4:15 PM"},
{:movie=>"Breaking a Monster", :time=>"6:45 PM"},
{:movie=>"The Citizen", :time=>"9:00 PM"},
{:movie=>"Citizen Kane", :time=>"9:40 PM"}
]
dates = [
'Tuesday 8, November',
'Wednesday 9, November',
'Thursday 10, November',
'Wednesday 9, November'
]
h = aggregate_by_date(dates, movies)
#=> {"Tuesday 8, November"=>[{:movie=>"The Neon Demon", :time=>"4:15 PM"}],
# "Wednesday 9, November"=>[{:movie=>"Breaking a Monster", :time=>"6:45 PM"},
# {:movie=>"Citizen Kane", :time=>"9:40 PM"}],
# "Thursday 10, November"=>[{:movie=>"The Citizen", :time=>"9:00 PM"}]}
Explanation
For i = 0 we compute:
(h[dates[i]] ||= []) << movies[i]
#=> (h[dates[i] = h[dates[i] || []) << movies[i]
#=> (h[dates[i] = nil || []) << movies[i]
#=> (h[dates[i] = []) << movies[i]
#=> h["Tuesday 8, November"]=>[{:movie=>"The Neon Demon", :time=>"4:15 PM"}]
h #=> {"Tuesday 8, November"=>[{:movie=>"The Neon Demon", :time=>"4:15 PM"}]}
For i = 1 the calculation is similar:
(h[dates[i]] ||= []) << movies[i]
#=> "Wednesday 9, November"=>[{:movie=>"Breaking a Monster", :time=>"6:45 PM"}]
h #=> {"Tuesday 8, November"=>[{:movie=>"The Neon Demon", :time=>"4:15 PM"}],
# "Wednesday 9, November"=>[{:movie=>"Breaking a Monster", :time=>"6:45 PM"}]}
For i = 2, once more, the calculation is similar:
(h[dates[i]] ||= []) << movies[i]
#=> "Thursday 10, November"=>[{:movie=>"The Citizen", :time=>"9:00 PM"}]
h #=> {"Tuesday 8, November"=>[{:movie=>"The Neon Demon", :time=>"4:15 PM"}],
# "Wednesday 9, November"=>[{:movie=>"Breaking a Monster", :time=>"6:45 PM"}],
# "Thursday 10, November"=>[{:movie=>"The Citizen", :time=>"9:00 PM"}]}
But for i = 3, things change, as h now has a key 'Wednesday 9, November', so the calculation is simpler:
(h[dates[i]] ||= []) << movies[i]
#=> (h[dates[i] = h[dates[i] || []) << movies[i]
#=> (h[dates[i] =
# [{:movie=>"Breaking a Monster", :time=>"6:45 PM"}] || []) << movies[i]
#=> h[dates[i] =
[{:movie=>"Breaking a Monster", :time=>"6:45 PM"}] << movies[i]
#=> h['Wednesday 9, November'] =
#=> [{:movie=>"Breaking a Monster", :time=>"6:45 PM"},
# {:movie=>"Citizen Kane", :time=>"9:40 PM"}]
h, which is now returned from the block, equals the hash produced in the example.
Alternative method
Here is another way this could be written, which I present without explanation.
def aggregate_by_date(dates, movies)
dates.zip(movies).group_by(&:first).
tap { |h| h.keys.each { |k| h[k] = h[k].map(&:last) } }
end