假设我有一个日期时间对象的排序列表times
。我希望从该列表中提取另一个列表,该列表可能更长或更短,但是它将包括原始列表中的至少一些(如果不是全部)元素,但是一些可能以下列方式重复:
首先是虚拟"开始时间"将被设置,这是最新的舍入到秒的时间,不晚于原始列表中的任何日期时间。例如,如果原始列表是
dts = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 42, 158749),
datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]
然后"开始时间"将是
start_time = datetime.datetime(2014, 8, 15, 13, 1, 41)
然后,这" start_time"每次迭代进行一秒,每次这样的迭代产生原始列表中的最后一个日期时间,该日期时间不晚于当前的时间"。当所有原始日期时间早于当前时间时,它将暂停。例如,给定上面的原始列表,输出应该是
output = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]
您能想到一种简单(高效)的方法来实现这一目标吗?
答案 0 :(得分:3)
使用bisect
module在生成器函数中查找每个datetime
对象。将起始参数限制为找到的最后一个位置。然后每个循环最多采用log N步骤来查找下一个值,其中N是仍然是候选元素的其余元素。
生成起始值就像在第一个值上调用.replace(microsecond=0)
一样简单;结束值只是排序输入中的最后一个值;只要您的“当前”位置低于结尾,添加一秒并找到其插入点;它之前的值是要产生的值。
import bisect
import datetime
def generate_last(dts):
current = dts[0].replace(microsecond=0)
end = dts[-1]
pos = 0
while current < end:
current += datetime.timedelta(seconds=1)
pos = bisect.bisect(dts, current, lo=pos)
yield dts[pos - 1]
演示:
>>> import bisect
>>> import datetime
>>> def generate_last(dts):
... current = dts[0].replace(microsecond=0)
... end = dts[-1]
... pos = 0
... while current < end:
... current += datetime.timedelta(seconds=1)
... pos = bisect.bisect(dts, current, lo=pos)
... yield dts[pos - 1]
...
>>> dts = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
... datetime.datetime(2014, 8, 15, 13, 1, 42, 158749),
... datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
... datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
... datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]
>>> pprint(list(generate_last(dts)))
[datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]