使用 takewhile (itertools) 考虑最后一次迭代

Posted

技术标签:

【中文标题】使用 takewhile (itertools) 考虑最后一次迭代【英文标题】:Taking into account last iteration with takewhile (itertools) 【发布时间】:2019-03-28 16:14:27 【问题描述】:

我需要遍历 .csv,直到名为“seguir”的布尔值变为 False。 问题是 takewhile 丢弃了最后一次迭代和值,我需要它,因为该行中 .csv 的值与我的问题相关。

for line in itertools.takewhile(lambda x: seguir, lectura):
    data2 = strintodate(line[1])
    data4 = strintodate(line[2])
    if data2 < data4:
        seguir = False
    escritura.writerow([programa + 1, data2, data2, line[4]])

有什么建议吗? 谢谢

【问题讨论】:

【参考方案1】:

您可以使用for 循环,其条件是在写入行后breaks:

for line in lectura:
    data3 = strintodate(line[1])
    data4 = strintodate(line[2])
    escritura.writerow([programa + 1, data2, data2, line[4]])
    if data2 < data4:
        break

【讨论】:

【参考方案2】:

这个问题的另一个更优雅的解决方案是改变那个时刻 您评估data2 &lt; data4:如果您在takewhile() 的谓词中这样做,它将允许您在处理中包含“最后一次”迭代。换句话说,如果你有 5 行 data2 &lt; data4 并且第六行有 data2 &gt;= data4,那么下面的 for-loop 将执行 6 次,最后一次允许你保留值。

代码变成这样:

data2, data4 = 2, 4
for line in itertools.takewhile(lambda x: data2 < data4, lectura):
    data2 = strintodate(line[1])
    data4 = strintodate(line[2])
    escritura.writerow([programa + 1, data2, data2, line[4]])

【讨论】:

【参考方案3】:

如果不做太多改变,你可以在 for 循环之外保留一个临时变量来存储上一行

prevLine = ""
for line in itertools.takewhile(lambda x: seguir, lectura):
    <check that prevLine is not empty string as it will be on first iteration>
    <do oepration involving prevLine>
    data3 = strintodate(line[1])
    data4 = strintodate(line[2])
    if data2 < data4:
        seguir = False
    escritura.writerow([programa + 1, data2, data2, line[4]])
    prevLine = line

【讨论】:

【参考方案4】:

blhsing's 解决方案是可行的方法,但是还有另一种方法可以给猫剥皮 - 使用 itertools.tee 创建一个紧跟其后的迭代器

iter1, iter2 = tee(lectura)
for line in itertools.takewhile(lambda x: seguir, iter1):
    next(iter2)
    data3 = strintodate(line[1])
    data4 = strintodate(line[2])
    if data2 < data4:
        seguir = False
    escritura.writerow([programa + 1, data2, data2, line[4]])
line = next(iter2)
data3 = strintodate(line[1])
data4 = strintodate(line[2])
escritura.writerow([programa + 1, data2, data2, line[4]])

一句话,丑。通过将data2 和其他元素的设置以及对writerow 的调用提取到一个单独的函数中,这在某种程度上是可以挽救的

【讨论】:

以上是关于使用 takewhile (itertools) 考虑最后一次迭代的主要内容,如果未能解决你的问题,请参考以下文章

Python标准库(3.x): itertools库扫盲

takeWhile() 与平面图的工作方式不同

为啥 takewhile() 会跳过第一行?

RxJS takeWhile 但包含最后一个值

Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析

Linq的TakeWhile的用法