如何对 API 中的日期和时间数据进行分组
How to group Date and time data from API
我正在尝试对从 API 获取的数据进行分组,以服务于我们的前端应用程序。我的意思是 "time" 组 "date"。
日期:{date1: [time1, time2, timeN], date2: [time1...]}
我的输入是这样的:
{"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"}
我的输出应该是这样的:
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"]}]
我正在尝试以这种方式执行此操作,但不会陷入疯狂循环。我有以下内容:
dates = Hash[input_data.map{|sd| [sd.date, [""]]}]
这给了我这样的数据输出:
{"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"=>[""]}
只有一种可能的方式:
input.each_with_object(Hash.new { |h, k| h[k] = [] }) do |h, m|
m[h['date']] << h['time']
end.map { |k, v| { date: k, avaliable_times: v } }
#=> [{:date=>"2017-04-04T00:00:00", :avaliable_times=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"]},
# {:date=>"2017-04-05T00:00:00", :avaliable_times=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]
实际上,如果没有 last map
,您的数据结构似乎会更简洁,我的意思是:
#=> {"2017-04-04T00:00:00"=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"],
# "2017-04-05T00:00:00"=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}
有很多方法可以做到这一点,一种方法是创建一个新的散列,并将默认值设置为一个数组,然后遍历结果并插入日期:
dates = Hash.new { |hash, key| hash[key] = [] }
input_data.each{ |sd| dates[sd["date"]] << sd["time"] }
可能还有更优雅的方式,但是
results = Hash.new
dates.each do |date|
d, t = date['date'].split('T') # (clean up/split date and time formatting)
results.key?(d) ? nil : results[d] = Array.new
results[d] << t
end
puts results
# => {"2017-04-04"=>["13:00:00", "14:00:00"], "2017-04-05"=>["12:00:00", "13:00:00"]}
您得到该输出是因为您的 map
函数实际上并未修改任何类型的数据结构。它只是返回一个新数组,其中包含包含日期的数组和一个包含空字符串的数组。基本上,这不会仅通过一次地图调用来完成。
所以,基本算法是:
- 查找所有唯一日期的数组
- 遍历唯一日期并使用
select
仅获取循环迭代中当前日期的 date/time 对
- 以您喜欢的格式设置数据
此代码将filteredDates
采用您需要数据的格式
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
这是 filteredDates
的样子:
{: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"]}]}
dates = [{"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"}]
dates.group_by { |g| g["date"] }.
map { |k,v| { date: k, available_times: v.map { |h| h["time"] } } }
#=> [{:date=>"2017-04-04T00:00:00",
# :available_times=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"]},
# {:date=>"2017-04-05T00:00:00",
# :available_times=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]
第一步产生如下中间值:
dates.group_by { |g| g["date"] }
#=> {"2017-04-04T00:00:00"=>
# [{"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T13:00:00"},
# {"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T14:00:00"}],
# "2017-04-05T00: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"}]}
我正在尝试对从 API 获取的数据进行分组,以服务于我们的前端应用程序。我的意思是 "time" 组 "date"。
日期:{date1: [time1, time2, timeN], date2: [time1...]}
我的输入是这样的:
{"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"}
我的输出应该是这样的:
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"]}]
我正在尝试以这种方式执行此操作,但不会陷入疯狂循环。我有以下内容:
dates = Hash[input_data.map{|sd| [sd.date, [""]]}]
这给了我这样的数据输出:
{"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"=>[""]}
只有一种可能的方式:
input.each_with_object(Hash.new { |h, k| h[k] = [] }) do |h, m|
m[h['date']] << h['time']
end.map { |k, v| { date: k, avaliable_times: v } }
#=> [{:date=>"2017-04-04T00:00:00", :avaliable_times=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"]},
# {:date=>"2017-04-05T00:00:00", :avaliable_times=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]
实际上,如果没有 last map
,您的数据结构似乎会更简洁,我的意思是:
#=> {"2017-04-04T00:00:00"=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"],
# "2017-04-05T00:00:00"=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}
有很多方法可以做到这一点,一种方法是创建一个新的散列,并将默认值设置为一个数组,然后遍历结果并插入日期:
dates = Hash.new { |hash, key| hash[key] = [] }
input_data.each{ |sd| dates[sd["date"]] << sd["time"] }
可能还有更优雅的方式,但是
results = Hash.new
dates.each do |date|
d, t = date['date'].split('T') # (clean up/split date and time formatting)
results.key?(d) ? nil : results[d] = Array.new
results[d] << t
end
puts results
# => {"2017-04-04"=>["13:00:00", "14:00:00"], "2017-04-05"=>["12:00:00", "13:00:00"]}
您得到该输出是因为您的 map
函数实际上并未修改任何类型的数据结构。它只是返回一个新数组,其中包含包含日期的数组和一个包含空字符串的数组。基本上,这不会仅通过一次地图调用来完成。
所以,基本算法是:
- 查找所有唯一日期的数组
- 遍历唯一日期并使用
select
仅获取循环迭代中当前日期的 date/time 对 - 以您喜欢的格式设置数据
此代码将filteredDates
采用您需要数据的格式
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
这是 filteredDates
的样子:
{: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"]}]}
dates = [{"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"}]
dates.group_by { |g| g["date"] }.
map { |k,v| { date: k, available_times: v.map { |h| h["time"] } } }
#=> [{:date=>"2017-04-04T00:00:00",
# :available_times=>["1754-01-01T13:00:00", "1754-01-01T14:00:00"]},
# {:date=>"2017-04-05T00:00:00",
# :available_times=>["1754-01-01T12:00:00", "1754-01-01T13:00:00"]}]
第一步产生如下中间值:
dates.group_by { |g| g["date"] }
#=> {"2017-04-04T00:00:00"=>
# [{"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T13:00:00"},
# {"date"=>"2017-04-04T00:00:00", "time"=>"1754-01-01T14:00:00"}],
# "2017-04-05T00: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"}]}