如何在循环中从生成器获取三个下一个值的集合

use*_*342 3 python iteration generator

我有一个问题,因为我无法找到解决问题的方法.

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

通常通过迭代生成我可以读取每一行.问题是在每次迭代时我需要读取当前行和下两行.

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

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'
Run Code Online (Sandbox Code Playgroud)

但在我的情况下,我需要得到这个:

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
Run Code Online (Sandbox Code Playgroud)

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

jad*_*k94 5

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

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)))
Run Code Online (Sandbox Code Playgroud)

如果它是你正在阅读的文件,你可以seek,readline然后回去,但它可能会变得混乱,所以你可以像任何其他迭代器一样对待它.

更新:每次迭代不仅仅有3个项目,它的工作效果很好,它的工作原理与其他项目相同.

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
Run Code Online (Sandbox Code Playgroud)

编辑2:在yield语句之前移动列表的串联,以避免必须两次.明智的改善性能.