Search code examples
rubydateparsingruby-hash

How to group Date and time data from API


I am trying to group data I am getting from an API to serve to our front application. I mean group "time" by "date". dates: {date1: [time1, time2, timeN], date2: [time1...]}

My input is like this:

{"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T13:00:00"}
{"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T14:00:00"}
{"date"=>"2017-04-05T00:00:00", "time"=>"1754-01-01T12:00:00"}
{"date"=>"2017-04-05T00:00:00", "time"=>"1754-01-01T13:00:00"}

And my output should be like this:

dates: [{date: "2017-04-04T00:00:00", availableTimes: ["1754-01-01T13:00:00", "1754-01-01T14:00:00"]}, {date: "2017-04-05T00:00:00", availableTimes: ["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]

I am trying to do this this way but without going into loop madness. I have the following:

dates  = Hash[input_data.map{|sd| [sd.date, [""]]}]

This gives me the data outpout like this:

{"2017-04-04T00:00:00"=>[""],
 "2017-04-05T00:00:00"=>[""],
 "2017-04-11T00:00:00"=>[""],
 "2017-04-12T00:00:00"=>[""],
 "2017-04-18T00:00:00"=>[""],
 "2017-04-19T00:00:00"=>[""],
 "2017-04-25T00:00:00"=>[""],
 "2017-04-26T00:00:00"=>[""]}

Solution

  • You are getting that output because your map function is not actually modifying any sort of data structure. It is simply returning a new array full of arrays that contain the date and an array with an empty string. Basically, this isn't going to be done with just a single map call.

    So, the basic algorithm would be:

    1. Find array of all unique dates
    2. Loop through unique dates and use select to only get the date/time pairs for the current date in the loop iteration
    3. Set up the data in the format you prefer

    This code will have filteredDates be in the format you need the data

    filteredDates = { dates: [] }
    uniqueDates = input_data.map { |d| d["date"] }.uniq # This is an array of only unique dates
    uniqueDates.each do |date|
        dateTimes = input_data.select { |d| d["date"] == date }
        newObj = { date: date }
        newObj[:availableTimes] = dateTimes.map { |d| d["time"] }
        filteredDates[:dates].push(newObj)
    end
    

    Here is what filteredDates will look like:

    {:dates=>[{:date=>"2017-04-04T00:00:00", :availableTimes=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"]}, {:date=>"2017-04-05T00:00:00", :availableTimes=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]}