简介
我想出了一个巧妙的解决方案来解决我的问题,但是,不太狡猾,它不起作用:-/
经过几个小时的点击调试器后,我认为,所以也许你可以验证这一点,它不起作用的原因是因为itertools.dropwhile
,在初始声明是固定的 - 而我希望可以在每个循环上更改谓词的输入参数。
下面的任务尝试选择一个开始日期,然后是其后的结束日期,然后是该日期之后的开始日期,最后一个日期之后的结束日期......依此类推,以便我们最终得到一系列日期间隔不重叠。开始日期来自一个列表,结束日期来自另一个列表。
以下解决方案循环遍历开始日期,然后遍历结束日期,使用 dropwhile
传递“过去”中的日期。第一次就可以完美运行。但在第二遍时,结束日期卡在“2009-12-14”。我打破了“isbefore”例程,这样我就可以看到它何时被测试,何时未被测试。不确定,但我认为正在发生的事情是整个 dropwhile
测试在第一次传递时就已确定,并且不会在每次传递时重新编译自身?就像我希望/期望的那样。
为了完成它,我希望将其全部包装在 while True
中,并通过 StopIteration
异常退出,从而提取完整的间隔序列。但它永远不会着火。当我尝试时,两个迭代器实际上都不会一直“下一步”到末尾。
问题
- 对于正在发生的事情,这个(一成不变的结论)正确吗?
- 有没有一种简短、干净、优雅的方式让它按照我希望的方式运行?我必须编写自己的 dropwhile 来按照我想要的方式运行吗?
代码
import itertools
import datetime
startdates = [
datetime.date(2009, 11, 5), datetime.date(2009, 11, 13),
datetime.date(2009, 12, 4), datetime.date(2009, 12, 7),
datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)]
enddates = [
datetime.date(2009, 10, 1), datetime.date(2009, 10, 2),
datetime.date(2009, 11, 4), datetime.date(2009, 12, 14),
datetime.date(2009, 12, 15),datetime.date(2009, 12, 30)]
enddate = datetime.date(1900, 1, 1)
startdate = datetime.date(1900, 1, 1)
def isbefore(a, b):
return a <= b
for startdate in itertools.dropwhile(lambda date: isbefore(date, enddate), startdates):
for enddate in itertools.dropwhile(lambda date: isbefore(date, startdate), enddates):
print startdate, enddate
break
电流输出
2009-11-05 2009-12-14
2009-11-13 2009-12-14
2009-12-04 2009-12-14
2009-12-07 2009-12-14
所需输出
2009-11-05 2009-12-14
2009-12-29 2009-12-30
细心的人会注意到我问了this question昨天出现了同样的问题,但是这个问题需要一个通用的解决方案,而这次我具体询问 dropwhile 的工作原理。
最佳答案
一旦 dropwhile
删除了满足谓词的项,它就会产生剩余的未修改的可迭代对象。使用 itertools.ifilterfalse
代替它可以提供您想要的输出,因为即使在初始运行后它也会继续处理谓词。
关于python - 'dropwhile' 是静态的吗?我可以让它动态吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12119422/