其他答案已修复您的错误,因此您的算法现在可以正常运行。
但是算法本身是错误的。你想在不过去的情况下获得最接近现在的东西。但是你写的是:
[x for x in itertools.takewhile(pred, examples)][-1]
想想这意味着什么。首先,takewhile
将返回示例,直到其中一个未通过谓词。然后你会拿最后一个成功的。因此,如果您的示例如下所示:
[now-3, now-10, now-5, now+3, now-9, now-1, now+9]
首先,takewhile
将产生now-3, now-10, now-5
然后停止,因为pred(now+3)
返回 False。然后,你拿最后一个,now-5
。
如果您按升序对示例进行排序,这将起作用:
[now-10, now-9, now-5, now-3, now-1, now+3, now+9]
Nowtakewhile
将产生直到 的所有东西now-1
,所以它产生的最后一件事就是你想要的。
但是您最初问题中的示例是按降序排列的,并且在对 Anthony Kong 的回答的评论中,您添加了一些根本不按任何顺序排列的示例。因此,您显然不能依赖它们按排序顺序排列。因此,一种可能的解决方法是对它们进行排序:
>>> import datetime, itertools, time
>>> currentTimeMachine = datetime.datetime.now()
>>> print [x for x in itertools.takewhile(lambda t: currentTimeMachine > datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S"), sorted(examples))][-1]
2012-12-10 02:06:45
或者,为了使事情更具可读性,打破最后一行,并摆脱无关的列表理解:
>>> exampleDates = [datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in examples]
>>> def beforeNow(t):
... return currentTimeMachine > t
>>> print list(itertools.takewhile(beforeNow, sorted(exampleDates))[-1]
然而,这是一种愚蠢的做事方式。您真正想要的是不在现在之后的示例中的最大值。所以只要把那个英文句子翻译成代码:
>>> print max(x for x in exampleDates if x <= currentTimeMachine)
让我们把它们放在一起:
>>> examples = ['2012-12-10 02:06:45', '2012-12-10 02:02:43', '2012-12-10 01:58:53']
>>> exampleDates = (datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in examples)
>>> currentTimeMachine = datetime.datetime.now()
>>> print max(t for t in exampleDates if t <= currentTimeMachine)
2012-12-10 02:06:45
我使用了生成器表达式而不是列表,exampleDates
因为您实际上不需要列表来处理任何只需要迭代一次的东西。如果您想保留它以供检查或重复使用,请将括号更改为方括号。
另外,我将 更改<
为<=
,因为您说“现在不晚”而不是“比现在早”(换句话说,现在应该算数)。
附带说明一下,因为您碰巧有 ISO 式时间戳,您实际上可以将它们排序为字符串:
>>> now = datetime.datetime.now()
>>> currentTimeMachine = datetime.datetime.strftime(now, "%Y-%m-%d %H:%M:%S")
>>> print max(t for t in examples if t <= currentTimeMachine)
2012-12-10 02:06:45
这样做没有充分的理由,并且当您获得格式略有不同的时间戳(例如,'2012-12-10 02:06:45'
比较之前'2012-12-10Z01:06:45'
)时,它总是会导致您出现错误,但这实际上不是您的原始代码的问题。