您可以使用zip 和islice 构造一个迭代器,它有自己的“未来”可用。
next(
filter(
lambda pair: isprime(pair[1]), # The predicate applied to a pair
zip(xs, islice(xs, 1, None)) # The iterator and its 'future'
),
(None, None) # A default pair in case no matches are found
)[0] # Retrieve the 'current' entry from the matching pair
在每个步骤中,您都有一对您可以认为是(present, future),谓词将应用于future。最后,我们解包present,它表示迭代器中最后一个不匹配的条目。
请注意,如所示,此实现不会返回列表中的最后一个条目,因为本质上,如果您将[a, b, c] 压缩到其自己的移位版本,您最终会得到一个比另一个短的。你可以使用zip_longest(来自itertools)来克服这个问题,但你需要在你的谓词中处理fillvalue(通常是None)。
正如评论中所述,这对生成器不起作用,因为它会消耗生成器。但是,使用折叠(Python 中的reduce)会变得更容易。首先,在更“Pythonic”的演示中,函数看起来像这样:
def fold(hist, cur):
stop, prev = hist
if stop:
return hist
if isprime(cur):
return (True, prev)
return (False, cur)
元组的第一个元素用作“停止”标记,第二个元素是我们的“针”。您可以将其与 reduce 一起使用:
reduce(fold, xs, (False, None))[1]
这并不完全是“一个衬里”,但我们可以将其压缩成lambda:
reduce(lambda z, x: (z if z[0] else ((1, z[1]) if isprime(x) else (0, x))), xs, (0, None))[1]