我有一堆带有datetime类型的开始和结束的时隙。给定特定的日期时间,我需要获取之前和之后的日期:
def get_before(timeslots, moment):
return [t for t in timeslots if t.end <= moment]
def get_after(timeslots, moment):
return [t for t in timeslots if t.start >= moment]
但是有两个可选参数,minimum和maximum,表示时隙必须在最大分钟数之内且在最小分钟数之外。
我们有以下插槽:
2018-06-27 09:00:00 - 2018-06-27 10:00:00
2018-06-27 10:00:00 - 2018-06-27 11:00:00
2018-06-27 11:00:00 - 2018-06-27 12:00:00
2018-06-27 12:00:00 - 2018-06-27 13:00:00
2018-06-27 13:00:00 - 2018-06-27 14:00:00
2018-06-27 14:00:00 - 2018-06-27 15:00:00
2018-06-27 15:00:00 - 2018-06-27 16:00:00
2018-06-27 16:00:00 - 2018-06-27 17:00:00
2018-06-27 17:00:00 - 2018-06-27 18:00:00
2018-06-27 18:00:00 - 2018-06-27 19:00:00
2018-06-27 19:00:00 - 2018-06-27 20:00:00
2018-06-27 20:00:00 - 2018-06-27 21:00:00
2018-06-27 21:00:00 - 2018-06-27 22:00:00
如果我们想要2018-06-27 15:00:00
之后的时隙,最少1小时,最多4小时,则得到:
2018-06-27 16:00:00 - 2018-06-27 17:00:00
2018-06-27 17:00:00 - 2018-06-27 18:00:00
2018-06-27 18:00:00 - 2018-06-27 19:00:00
2018-06-27 19:00:00 - 2018-06-27 20:00:00
这是我的实现方式
def get_before(timeslots, moment, minimum=None, maximum=None):
tslots = [t for t in timeslots if t.end <= moment]
if maximum is not None:
maxdelta = datetime.timedelta(minutes=maximum)
tslots = [t for t in tslots if t.end + maxdelta >= moment]
if minimum is not None:
mindelta = datetime.timedelta(minutes=minimum)
tslots = [t for t in tslots if t.end <= moment - mindelta]
return tslots
def get_after(timeslots, moment, minimum=None, maximum=None):
tslots = [t for t in timeslots if t.start >= moment]
if maximum is not None:
maxdelta = datetime.timedelta(minutes=maximum)
tslots = [t for t in tslots if t.start - maxdelta <= moment]
if minimum is not None:
mindelta = datetime.timedelta(minutes=minimum)
tslots = [t for t in tslots if t.start >= moment + mindelta]
return tslots
问题是,对于每个过滤功能,我都会对timeslots
列表进行三次迭代:一次获取该时刻之前或之后的列表,其次获取最大时间范围内的列表,其次过滤这些列表超出最小时间范围。
这些函数将被非常频繁地调用,所以我想知道是否有一种方法可以合并筛选,以便仅对列表进行一次迭代。
答案 0 :(得分:1)
这可以用间隔树有效地解决。参见https://en.wikipedia.org/wiki/Interval_tree
根据Google的快速搜索,似乎有很多python实现。
答案 1 :(得分:0)
您可以基于最大值和最小值创建lambda函数。然后在单个列表理解中应用该函数。
maximum = 10
minimum = 5
if maximum:
f = lambda x : x <= maximum
if minimum:
f = lambda x : x >= minimum
if maximum and minimum:
f = lambda x : x <= maximum and x >= minimum
print [ x for x in range(50) if f(x) ]
输出:
[sri@localhost ~]$ python test.py
[5, 6, 7, 8, 9, 10]
此外,如果您对时间进行排序,找到最大值后就可以停止搜索。
答案 2 :(得分:0)
只需计算所有内容一次并设置有用的默认值:
def get_before2(timeslots, moment, minimum=0, maximum=1440):
maxdelta = moment - datetime.timedelta(minutes=maximum)
mindelta = moment - datetime.timedelta(minutes=minimum)
tslots = [t for t in timeslots if t.end >= maxdelta and t.end <= mindelta]