[英]how to get set of three next values from generator in a loop
I have one question because I can not find a solution for my problem. 我有一个问题,因为我无法找到解决问题的方法。
gen is a generator (result of difflib.Differ.compare()): gen是一个生成器(difflib.Differ.compare()的结果):
normally by iterating over gen I can read each line. 通常通过迭代生成我可以读取每一行。 The problem is that on each iteration I need to read the current line and the two next lines.
问题是在每次迭代时我需要读取当前行和下两行。
Example (normal output by iterating line by line): 示例(逐行迭代的正常输出):
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'
but in my case I need to get this: 但在我的情况下,我需要得到这个:
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
I was trying to play with gen.send(), itertools.islice(), but I can not find the proper solution. 我试图使用gen.send(),itertools.islice(),但我找不到合适的解决方案。 I don't want to convert this generator into a list (then I could read next1 as gen[i + 1], next2 as gen[i + 2], but this is totally inefficient when the diff output is large.
我不想将这个生成器转换成一个列表(然后我可以读取next1作为gen [i + 1],next2作为gen [i + 2],但是当diff输出很大时,这是非常低效的。
This is what I'd suggest as a general solution for any iterator/generator. 这就是我建议作为任何迭代器/生成器的通用解决方案。 I think it's most efficient this way.
我认为这种方式效率最高。
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)))
If it was a file you were reading from, you could seek
, readline
then go back, but it might get messy, so you can treat it as any other iterator. 如果它是你正在阅读的文件,你可以
seek
, readline
然后返回,但它可能会变得混乱,所以你可以像任何其他迭代器一样对待它。
UPDATE : Made it work nicely for more than just 3 items per iteration, it works just as the other does. 更新 :每次迭代不仅仅有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
Edit 2 : Moved the concatenation of the lists before the yield statement, just to avoid having to make it twice. 编辑2 :在yield语句之前移动列表的串联,以避免必须两次。 Slight improvement performance wise.
明智的改善性能。
Try keeping temporary variables. 尝试保留临时变量。
line = iterator.next()
next1 = iterator.next()
for next2 in iterator:
#do stuff
line = next1
next1 = next2
There's a recipe in the itertools
docs , pairwise()
. 在
itertools
docs中有一个配方, itertools
pairwise()
。 It can be adapted: 它可以适应:
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):
...
It can also be generalized: 它也可以概括为:
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):
...
如何将三个序列压缩在一起?
izip_longest(gen, islice(gen,1,None), islice(gen,2,None), fillvalue=None)
You could use something like this: 你可以使用这样的东西:
def genTriplets(a):
first = a.next()
second = a.next()
third = a.next()
while True:
yield (first, second, third)
first = second
second = third
try:
third = a.next()
except StopIteration:
third = None
if (first is None and second is None and third is None):
break
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.