首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在循环中从生成器中获取一组三个下一个值

如何在循环中从生成器中获取一组三个下一个值
EN

Stack Overflow用户
提问于 2012-12-06 04:41:07
回答 5查看 1.1K关注 0票数 3

我有一个问题,因为我找不到解决问题的办法。

gen是一个生成器(difflib.Differ.compare()的结果):

通常,通过迭代gen,我可以读取每一行。问题是,在每次迭代中,我需要读取当前行和下两行。

示例(逐行迭代的正常输出):

代码语言:javascript
运行
复制
iteration 1:
    line = 'a'
iteration 2:
    line = 'b'
iteration 3:
    line = 'c'
iteration 4:
    line = 'd'
iteration 5:
    line = 'e'
iteration 6:
    line = 'f'
iteration 7: 
    line = 'g'

但在我的例子中,我需要得到这个:

代码语言:javascript
运行
复制
iteration 1:
    line = 'a'
    next1 = 'b'
    next2 = 'c'
iteration 2:
    line = 'b'
    next1 = 'c'
    next2 = 'd'
iteration 3:
    line = 'c'
    next1 = 'd'
    next2 = 'e'
iteration 4:
    line = 'd'
    next1 = 'e'
    next2 = 'f'
iteration 5:
    line = 'e'
    next1 = 'f'
    next2 = 'g'
iteration 6:
    line = 'f'
    next1 = 'g'
    next2 = None
iteration 7: 
    line = 'g'
    next1 = None
    next2 = None

我试着使用gen.send(),itertools.islice(),但是我找不到合适的解决方案。我不想将这个生成器转换为列表(然后我可以将next1读作geni + 1,将next2读作geni + 2,但当diff输出很大时,这是完全低效的。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-06 04:55:41

尝试保留临时变量。

代码语言:javascript
运行
复制
line = iterator.next()
next1 = iterator.next()

for next2 in iterator:
    #do stuff
    line = next1
    next1 = next2
票数 3
EN

Stack Overflow用户

发布于 2012-12-06 05:03:48

这就是我建议的任何迭代器/生成器的通用解决方案。我认为这种方式是最有效的。

代码语言:javascript
运行
复制
def genby3(gen):
    it = iter(gen) # Make it a separate iterator, to avoid consuming it totally
    L1 = it.next() # Get the first two elements
    L2 = it.next()
    for L3 in it:
        yield [L1, L2, L3] # Get the results grouped in 3
        L1, L2 = L2, L3 # Update the last 2 elements
    yield [L2, L3, None] # And take care of the last 2 cases
    yield [L3, None, None]

print list(genby3(xrange(10)))

如果这是一个你正在读取的文件,你可以seekreadline,然后返回,但是它可能会变得混乱,所以你可以把它当作任何其他迭代器。

UPDATE:使其在每次迭代中可以很好地处理3个以上的项目,它的工作方式与其他方式相同。

代码语言:javascript
运行
复制
def genby(gen, n):
    assert n>=1, 'This does not make sense with less than one element'
    it = iter(gen)
    last = list(it.next() for i in xrange(n-1))

    for nth_item in it:
        last = last+[nth_item]
        yield last
        last.pop(0)

    for i in xrange(n-1):
        last = last+[None]
        yield last
        last.pop(0)

r = xrange(10)
for i, n in enumerate(genby(r, 3)):
    print i, 'iteration'
    print '\t', n

编辑2:将列表的连接移到了yield语句之前,以避免重复两次。在性能方面稍有改进。

票数 6
EN

Stack Overflow用户

发布于 2012-12-06 05:09:44

有一个recipe in the itertools docspairwise()。它可以进行改编:

代码语言:javascript
运行
复制
from itertools import tee, izip_longest

def triplewise(iterable):
    xs, ys, zs = tee(iterable, 3)
    next(ys, None)
    next(zs, None)
    next(zs, None)
    return izip_longest(xs, ys, zs)

for line, next1, next2 in triplewise(gen):
    ...

它也可以泛化为:

代码语言:javascript
运行
复制
from itertools import tee, izip, izip_longest, islice

no_fillvalue = object()

def nwise(iterable, n=2, fillvalue=no_fillvalue):
    iters = (islice(each, i, None) for i, each in enumerate(tee(iterable, n)))
    if fillvalue is no_fillvalue:
        return izip(*iters)
    return izip_longest(*iters, fillvalue=fillvalue)

for line, next1, next2 in nwise(gen, 3, None):
    ...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13732036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档