# below is the example of list of dates:
date_list = [date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 5)]
我想计算所有连续的日期并制作一个字典,其中键值为开始日期,值为连续天数。
dic = {date(2021, 1, 2): 2, date(2021, 1, 5): 1}
谁能帮我完成上述任务我应该采取哪些步骤?我应该以不同的方式解决问题吗?非常感谢。
答案 0 :(得分:1)
这更像是一个算法问题,这里我列出了一些测试用例的代码
from datetime import date
from datetime import timedelta
def is_consecutive(date1, date2):
return True if date1 + timedelta(days=1) == date2 else False
def my_func(date_list):
if not date_list:
return {}
if len(date_list) == 1:
return {date_list[0]: 1}
date_list.sort()
res = {}
start_date = date_list[0]
cnt = 1
for idx, cur_date in enumerate(date_list[1:], start=1):
# print(idx, cur_date)
if is_consecutive(date_list[idx - 1], cur_date):
cnt += 1
else:
res[start_date] = cnt
start_date = cur_date
cnt = 1
else:
res[start_date] = cnt
return res
if __name__ == "__main__":
# below is the example of list of dates:
date_list = [date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 5)]
# {datetime.date(2021, 1, 2): 2, datetime.date(2021, 1, 5): 1}
print(my_func(date_list))
date_list = [date(2021, 1, 5), date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 6), date(2021, 1, 31),
date(2021, 2, 1), date(2021, 2, 2)]
# {datetime.date(2021, 1, 2): 2, datetime.date(2021, 1, 5): 2, datetime.date(2021, 1, 31): 3}
print(my_func(date_list))
date_list = [date(2021, 1, 5)]
# {datetime.date(2021, 1, 5): 1}
print(my_func(date_list))
date_list = []
# {}
print(my_func(date_list))
答案 1 :(得分:0)
有多种方法可以解决您的问题。在这种情况下,一个简单而有效的方法是使用 for
循环来检查条件(日期是连续的)是否适用于当前循环项和“正在进行的”日期组:
from datetime import date
date_list = [date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 5)]
result = {}
c = date_list[0]
n = 1
for d in date_list[1:]:
if (d - c).days == n:
n = n + 1
else:
result[c] = n
c = d
n = 1
result[c] = n
print(result)
我们从一个“组”开始,我们在其中放置第一个日期和一个计数器 n
,用于计算组中元素的数量。然后我们开始循环(从第二项开始)。在每次迭代时,我们都会检查条件:当前日期是从组中的第一个日期算起的未来 n
天吗?如果是,我们增加 n
并继续,否则我们将数据存储在字典中。请注意,我说的是一组“日期”,但您不需要存储所有日期:第一个和 n
(该组跨越的天数)在这里就足够了。
重要提示:使用这种方法时,您始终需要考虑到需要在循环外处理最后一组项目这一事实。
正如我所说,还有其他方法:我选择这种方法是因为,恕我直言,它的工作原理很容易理解。
答案 2 :(得分:0)
您需要遍历 date_list
并将每个日期与前一个日期进行比较,看看它们是否是连续的日子。假设您使用内置的 datetime.date 类,您可以使用 toordinal() 方法来轻松比较日期。您也可以使用 1 天的 timedelta。您将需要跟踪连续日期链中的第一个日期,以便您可以继续在字典中访问它。
假设您的日期列表已排序,以下代码应该可以工作。
from datetime import date
date_list = [date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 5)]
dic = {}
date_range_start = None
for i in range(len(date_list)):
if i == 0:
date_range_start = date_list[i]
dic[date_range_start] = 1
else:
if date_list[i].toordinal() - date_list[i-1].toordinal() == 1:
dic[date_range_start] += 1
else:
date_range_start = date_list[i]
dic[date_range_start] = 1
答案 3 :(得分:0)
我会这样做:
首先通过执行 date_list.sort()
对列表进行排序,这很重要,因为如果不进行排序,您将不会得到正确的结果。
然后就用for循环遍历整个列表,通过设置变量current_date
来跟踪前一天,将当天与前一天和当天进行比较,如果连续则递增计数器,例如 current_max_consecutive_day
else 使用新日期和计数器重置前一个日期。
from datetime import date
date_list = [date(2021, 1, 2), date(2021, 1, 3), date(2021, 1, 5)]
date_list.sort() # if the list is not sorted, then please sort it
dic = {}
current_max_consecutive_day = 1
current_date = date_list[0]
# This only work if the list is sorted
for d in date_list:
if d.day-current_date.day == 1:
# if we found a consecutive day then add it to the dictionary
current_max_consecutive_day += 1
else:
# otherwise create a new item in the dic and restart the count
current_max_consecutive_day = 1
current_date = d
dic[current_date] = current_max_consecutive_day
答案 4 :(得分:0)
您可以将列表转换为字典,每个日期的计数为 1。然后以每天为起点合并连续的日期:
from datetime import date,timedelta
date_list = [date(2021, 1, 3), date(2021, 1, 2), date(2021, 1, 5)]
dic = dict.fromkeys(date_list,1) # start with each date = span of 1
for d in date_list: # try to merge each date with next ones
c = d
while c in dic: # get consecutive dates starting from d
if c>d: dic[d] += dic.pop(c) # merge/remove later date
c += timedelta(days=1) # check further
print(dic)
# {datetime.date(2021, 1, 2): 2, datetime.date(2021, 1, 5): 1}
即使日期不是按升序排列也可以使用,因此您不需要排序并且时间复杂度为 O(n)
请注意,此解决方案没有考虑列表中重复日期的可能性(即,即使列表中有多个实例,每个日期也仅计为 1)