我正在处理TOP,有一个分配任务说,给定一个日期-时间列表,例如:
dates = [
"11/12/08 15:00", "11/12/08 16:05", "11/12/08 17:18", "11/13/08 1:32",
"11/13/08 16:40", "11/13/08 18:17", "11/13/08 21:19", "11/16/08 11:44",
"11/16/08 13:54", "11/16/08 20:20", "11/17/08 19:41", "11/19/08 21:56",
"11/20/08 16:25", "11/23/08 20:44"
]
找出一天中注册人数最多的时间。使用注册日期和时间,我们想了解的注册高峰时间
我想知道这个公式是什么,或者一步一步地计算它。顺便说一下,这是在ruby 中
谢谢!
有很多方法可以解决这个问题。这里有一个:将每个日期映射到一个只包含年/月/天/小时(即不包含分钟或秒(的字符串,然后tally
结果。然后,您可以查看哪个结果最常见(或者您想了解的关于聚合数据的其他信息(。
dates
.map { |date| DateTime.strptime(date, '%m/%d/%Y %H:%M') }
.tally
如果你的日期格式始终相同,并且你想要一天中最常见的时间(不在乎有多少天(,
然后你可以做
dates.group_by {|s| s.match(/d{1,2}/d{1,2}/d{1,2} (d{1,2}):d{1,2}/)[1]}.max_by {|k,v| v.size}[0]
这实际上只是在你所有的日期中循环,将同一小时的时间分组在一起,然后选出最常见的小时
编辑:或者使用Tom Lord的答案中的DateTime使其更可读:
dates.group_by {|date| DateTime.strptime(date, '%m/%d/%Y %H:%M').hour }.max_by {|k,v| v.size}[0]
我想您希望找到dates
中所有日期中注册人数最多的时间。
步骤1:使用Enumerable#计数将小时数映射到注册人数
h = dates.map { |date| date[/d+(?=:)/] }.tally
#=> {"15"=>1, "16"=>3, "17"=>1, "1"=>1, "18"=>1, "21"=>2, "11"=>1,
# "13"=>1, "20"=>2, "19"=>1}
正则表达式CCD_;匹配紧跟冒号的一个或多个(+
(数字(d
(,(?=:)
是正向预视";。
中间计算为:
dates.map { |date| date[/d+(?=:)/] }
#=> ["15", "16", "17", "1", "16", "18", "21", "11", "13", "20",
# "19", "21", "16", "20"]
tally
在Ruby v.2.7中首次亮相。要支持早期版本,请将tally
替换为
each_with_object(Hash.new(0)) { |s,h| h[s] += 1 }
步骤2:使用Enumerable#max_by按小时确定最大注册人数
peak_nbr = h.max_by(&:last).last
#=> 3
这表明每小时的最大注册人数为3
。
中间计算为:
h.max_by(&:last)
#=> ["16", 3]
如果只想任何小时都有最多的注册人数(即使他们在注册人数最多的小时内是平局(,可以简单地停止这种中间计算。
步骤3:使用Hash#select确定peak_nbr
注册者的小时数
h.select { |_hr,nbr| nbr == peak_nbr }
#=> {"16"=>3}
这表明"16"
是唯一一个注册人数最多的小时(3
(。如果在"12"
小时内也有3
注册者,那么这个散列将是{"16"=>3, "12"=>3}
。要只获取高峰时间,请写入
h.select { |_hr,nbr| nbr == peak_nbr }.keys
#=> ["16"]
我编写了第一个块变量_hr
,下划线向读取器发出信号,表示块计算中未使用该块变量。这是常见的做法(只使用_
作为变量名(。