我正在做一些需要一个前瞻标记的解析.我想要的是一个快速函数(或类?),它将采用迭代器并将其转换为表单中的元组列表(token,lookahead),这样:
>>> a = ['a', 'b', 'c', 'd']
>>> list(lookahead(a))
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', None)]
Run Code Online (Sandbox Code Playgroud)
基本上,这对于在这样的迭代器中展望是很方便的:
for (token, lookahead_1) in lookahead(a):
pass
Run Code Online (Sandbox Code Playgroud)
虽然,我不确定在itertools中是否有这个技术或功能的名称已经会这样做.有任何想法吗?
谢谢!
Joh*_*ooy 11
如果你只是使用列表,有更简单的方法 - 请参阅Sven的回答.这是为一般迭代器执行此操作的一种方法
>>> from itertools import tee, izip_longest
>>> a = ['a', 'b', 'c', 'd']
>>> it1, it2 = tee(iter(a))
>>> next(it2) # discard this first value
'a'
>>> [(x,y) for x,y in izip_longest(it1, it2)]
# or just list(izip_longest(it1, it2))
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', None)]
Run Code Online (Sandbox Code Playgroud)
以下是如何在问题循环中使用它.
>>> it1,it2 = tee(iter(a))
>>> next(it2)
'a'
>>> for (token, lookahead_1) in izip_longest(it1,it2):
... print token, lookahead_1
...
a b
b c
c d
d None
Run Code Online (Sandbox Code Playgroud)
最后,这是您正在寻找的功能
>>> def lookahead(it):
... it1, it2 = tee(iter(it))
... next(it2)
... return izip_longest(it1, it2)
...
>>> for (token, lookahead_1) in lookahead(a):
... print token, lookahead_1
...
a b
b c
c d
d None
Run Code Online (Sandbox Code Playgroud)
我喜欢Sven和gnibbler的答案,但出于某种原因,我喜欢滚动自己的发电机.
def lookahead(iterable, null_item=None):
iterator = iter(iterable) # in case a list is passed
prev = iterator.next()
for item in iterator:
yield prev, item
prev = item
yield prev, null_item
Run Code Online (Sandbox Code Playgroud)
测试:
>>> for i in lookahead(x for x in []):
... print i
...
>>> for i in lookahead(x for x in [0]):
... print i
...
(0, None)
>>> for i in lookahead(x for x in [0, 1, 2]):
... print i
...
(0, 1)
(1, 2)
(2, None)
Run Code Online (Sandbox Code Playgroud)
编辑:Karl和ninjagecko提出了一个很好的观点 - 传入的序列可能包含None,因此使用None最终的前瞻值可能会导致歧义.但是没有明显的选择; 在许多情况下,模块级常量可能是最好的方法,但对于像这样的一次性函数可能有点过分 - 更不用说bool(object()) == True可能导致意外行为的事实.相反,我添加了null_item一个默认值为的参数None- 这样用户可以传递任何对他们需要有意义的东西,无论是简单的object()哨兵,自己创造的常量,还是具有特殊行为的类实例.由于大部分时间None都是明显的,甚至可能是预期的行为,因此我将其None作为默认行为.
通常的方法是为列表执行此a操作
from itertools import izip_longest
for token, lookahead in izip_longest(a, a[1:]):
pass
Run Code Online (Sandbox Code Playgroud)
对于最后一个令牌,您将获得None前瞻性令牌.
如果要避免引入列表的副本a[1:],可以islice(a, 1, None)改为使用.对于任意迭代的略微修改,请参阅gnibbler的答案.对于一个简单易用的生成器函数也适用于任意迭代,请参阅senderle的答案.