将连续日期与 Python 组合在一起 [英] Group consecutive dates together with Python

查看:62
本文介绍了将连续日期与 Python 组合在一起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于:

dates = [
  datetime(2014, 10, 11), 

  datetime(2014, 10, 1), 
  datetime(2014, 10, 2),
  datetime(2014, 10, 3),

  datetime(2014, 10, 5), 
  datetime(2014, 10, 5), 
  datetime(2014, 10, 6), 

  datetime(2014, 10, 22), 
  datetime(2014, 10, 20),
  datetime(2014, 10, 21),

  datetime(2014, 10, 9), 

  datetime(2014, 10, 7),
  datetime(2014, 10, 6)
]

预期输出:

expect = [
  [datetime(2014, 10, 1), datetime(2014, 10, 3)],
  [datetime(2014, 10, 5), datetime(2014, 10, 7)],
   datetime(2014, 10, 9),
   datetime(2014, 10, 11),
  [datetime(2014, 10, 20), datetime(2014, 10, 22)]
]

在 Python 中的实现:

from datetime import datetime, timedelta

def parse_date_ranges(dates):
    if(not dates or not len(dates) > 0):
        return False

    # make sure to order dates
    dates.sort()

    # init values
    result  = []
    tupl    = [dates[0], dates[0]]
    it      = iter(dates)
    date    = True

    def add_tuple_to_result(tuple):
        # if first part of tuple differs from last part -> add full tuple
        # else -> add first part of tuple only
        result.append(tupl if tupl[0] != tupl[1] else tupl[0])

    while date:
        # get next date or False if no next date
        date = next(it, False)

        # filter double dates
        if(date in tupl):
            continue

        elif(date):
            if(date - timedelta(days=1) == tupl[1]):
                # consecutive date, so add date to end of current tuple
                tupl[1] = date
            else:
                # gap larger than 1 day: add current tuple to result
                # and create new tuple
                add_tuple_to_result(tupl)
                tupl = [date, date]

        else:
            # date == false, so this is the last step.
            # add the current tuple to result
            add_tuple_to_result(tupl)

    return result

有关更多测试,请参阅 https://gist.github.com/mattes/8987332,也是.

See https://gist.github.com/mattes/8987332 for some more tests, too.

问题

该实现有效,但我是 Python 新手.所以我想知道是否有更好的方法来解决这个问题?还是刚刚好?

The implementation works, but I am new to Python. So I was wondering if there are better ways to solve this issue? Or is it just fine?

推荐答案

我喜欢 itertools:

from itertools import tee, zip_longest
from datetime import datetime, timedelta

one_day = timedelta(days=1)

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return zip_longest(a, b, fillvalue=None)

def collapse_ranges(sorted_iterable, inc):
    pairs = pairwise(sorted_iterable)
    for start, tmp in pairs:
        if inc(start) == tmp:
            for end, tmp in pairs:
                if inc(end) != tmp:
                    break
            yield start, end
        else:
            yield start

# dates = [...]

numbers = [11, 1, 2, 3, 5, 5, 6, 22, 20, 21, 9, 7, 6]

if __name__ == '__main__':
    import pprint
    for each in collapse_ranges(sorted(set(dates)), lambda d: d + one_day):
        pprint.pprint(each)
    for each in collapse_ranges(sorted(set(numbers)), (1).__add__):
        pprint.pprint(each)

结果:

(datetime.datetime(2014, 10, 1, 0, 0), datetime.datetime(2014, 10, 3, 0, 0))
(datetime.datetime(2014, 10, 5, 0, 0), datetime.datetime(2014, 10, 7, 0, 0))
datetime.datetime(2014, 10, 9, 0, 0)
datetime.datetime(2014, 10, 11, 0, 0)
(datetime.datetime(2014, 10, 20, 0, 0), datetime.datetime(2014, 10, 22, 0, 0))
(1, 3)
(5, 7)
9
11
(20, 22)

这篇关于将连续日期与 Python 组合在一起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆