如何计算日期列表中的连续天数

时间:2021-02-05 07:48:13

标签: python list date dictionary count

# 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}

谁能帮我完成上述任务我应该采取哪些步骤?我应该以不同的方式解决问题吗?非常感谢。

5 个答案:

答案 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)

相关问题