Python:如何在时间对象列表中找到连续的时间间隔?

时间:2014-12-11 11:07:20

标签: python algorithm python-2.7

我有一个字典,其键是日期对象,值是时间对象列表。

timeSlots = {
    datetime.date(2014, 12, 11): [
        datetime.time(8, 0),
        datetime.time(8, 30),
        datetime.time(9, 0),
        datetime.time(9, 30),
        datetime.time(12, 0),
        datetime.time(12, 30),
        datetime.time(13, 0),
        datetime.time(13, 30),
        datetime.time(14, 0),
        datetime.time(14, 30)
    ],
    datetime.date(2014, 12, 12): [
        datetime.time(8, 0),
        datetime.time(8, 30),
        datetime.time(9, 0),
        datetime.time(9, 30),
        datetime.time(12, 0),
        datetime.time(12, 30),
        datetime.time(13, 0),
        datetime.time(13, 30),
        datetime.time(14, 0),
        datetime.time(14, 30)
    ]
}

输入:30分钟 输出:{datetime.date(2014,12,11):[90,150],datetime.date(2014,12,12):[90,150]}

如何计算:

  1. 假设我的间隔是输入中提供的30分钟。

  2. 获取第一个时段列表。开始看到8:00:00和8:30:00之间的差异是30分钟,这与收到的输入相同,所以再次转到9:00:00的列表的下一个要素(同样的情况8:30:00和9:00:00有30分钟差异)等等。

  3. 在12:00:00停止,因为差异超过了9:30:00列表中前一个元素的30分钟。

  4. 计算8:00:00至9:30:00之间的差异,并以分钟为单位返回90分钟。

  5. 继续此过程,您将获得输出。

  6. 希望我很清楚。

    最好的方法是什么?

    TIA

2 个答案:

答案 0 :(得分:1)

好的,我会第一个承认也许这不是最诡计多端的方式,但这是我的解决方案:

import datetime

def get_difference(d, times):
    first = datetime.datetime.combine(d, times[0])
    second = datetime.datetime.combine(d, times[1])
    return second - first

def solution(ts, interval):
    results = []
    outputDict = {}
    acc = datetime.timedelta()
    for key in ts:
        for item in range(len(ts[k])-1):
            delta = get_difference(key, ts[key][item:item+2])
            if delta > interval:
                results.append(acc)
                acc = datetime.timedelta()
            else:
                acc += delta
        results.append(acc)
        acc = datetime.timedelta()
        outputDict[key] = [result.total_seconds() / 60 for result in results]
        results = []
    return outputDict

它提供了您描述的确切输出:

>>> solution(timeSlots, datetime.timedelta(0, 1800))   #Interval needs to be in seconds
{datetime.date(2014, 12, 12): [90.0, 150.0], datetime.date(2014, 12, 11): [90.0, 150.0]}

答案 1 :(得分:0)

我不知道我是否完全按照你的意思,但试试这个功能。它会为interval中的每个键返回一个生成器,该生成器会分割您想要的索引(长度超过dict)。

import datetime

timeSlots = {
    datetime.date(2014, 12, 11): [
        datetime.time(8, 0),
        datetime.time(8, 30),
        datetime.time(9, 0),
        datetime.time(9, 30),
        datetime.time(12, 0),
        datetime.time(12, 30),
        datetime.time(13, 0),
        datetime.time(13, 30),
        datetime.time(14, 0),
        datetime.time(14, 30)]
    ,datetime.date(2   interval = 30


    def get_consec(time_slots):
        for key, value in time_slots.iteritems():
            print "date: %s" % key
            last_index = 0
            diffs = zip(value[:-1], value[1:])
            print "diffs: %s" % diffs
            index = None
            for index in range(len(diffs)):
                start = diffs[index][0]
                end = diffs[index][1]
                if (end.hour * 60 + end.minute) - (start.hour * 60 + start.minute) > interval:
                    print "splitting: %s"  % str((start ,end))
                    yield value[last_index: index+1]
                    last_index = index + 1
            if index and index != last_index:
                yield value[last_index: index + 2]
            else:
                yield value

    print list(get_consec(timeSlots))014, 12, 12): [
            datetime.time(8, 0),
            datetime.time(8, 30),
            datetime.time(9, 0),
            datetime.time(9, 30),
            datetime.time(12, 0),
            datetime.time(12, 30),
            datetime.time(13, 0),
            datetime.time(13, 30),
            datetime.time(14, 0),
            datetime.time(14, 30)
        ]
    ,datetime.date(2014, 12, 13): [
        datetime.time(8, 0),
    ]
    ,datetime.date(2014, 12, 14): [
        datetime.time(8, 0),
        datetime.time(8, 30),
    ]

    ,datetime.date(2014, 12, 15): [
        datetime.time(8, 0),
        datetime.time(8, 40),
    ]
}

interval = 30

def get_consec(time_slots):
    for key, value in time_slots.iteritems():
        print "date: %s" % key
        last_index = 0
        diffs = zip(value[:-1], value[1:])
        print "diffs: %s" % diffs
        index = None
        for index in range(len(diffs)):
            start = diffs[index][0]
            end = diffs[index][1]
            if (end.hour * 60 + end.minute) - (start.hour * 60 + start.minute) > interval:
                print "splitting: %s"  % str((start ,end))
                yield (key, value[last_index: index+1], )
                last_index = index + 1
        if index is not None:
            print "finished with last: %d, index: %d" % (last_index, index)
            yield (key, value[last_index: index+2], )
        else:
            print "no iteration for %s" % value
            yield (key, value, )

print '\n'.join(map(str, list(get_consec(timeSlots))))

修改

添加完整代码以方便测试。它适用于某些情况,请务必添加更多!