2013-10-06 71 views
2

假设我在Python中有一个生成器,除了前10次迭代和最后10次迭代之外,我想遍历其中的所有内容。 itertools.islice支持这种分片操作的第一部分,但不支持第二部分。有没有简单的方法来实现这一点?索引形式生成器的末尾

回答

1

不仅没有简单的方法,而且根本没有办法,如果你想允许任何生成器(或任何可迭代的)。一般来说,无法知道自己是从发电机末端开始的10个项目,还是无法知道发电机是否结束。发电机一次只给你一件物品,并且不告诉你有多少物品“遗留”。你将不得不迭代整个生成器,保留最近10个项目的临时缓存,然后在发生器终止时(或者如果!)生成这些项目。

请注意“或如果”。发电机不一定是有限的。对于无限生成器来说,没有“最后”10个元素这样的事情。

2

像这样的东西可能会完成这项工作。编辑:增加使用deque每个评论。

from collections import deque 
def generator(): 
    for i in ['ignore'] * 10 + ['yield this'] * 10 + ['ignore'] * 10: 
     yield i 


def func(mygenerator): 
    cache = deque() 
    for i, item in enumerate(mygenerator()): 
     if i < 10: 
      continue 
     cache.appendleft(item) 
     if len(cache) > 10: 
      yield cache.pop() 

for i in func(generator): 
    print i 
+0

我正在考虑类似的解决方案。如果速度很重要,则可能必须使用缓存的'Queue'对象。据我所知,列表并未针对从头开始重复插入进行优化。 –

+0

使用'collections.deque'。它旨在允许在每一端快速访问值,所以'insert'(如'pushleft')和'pop'调用都会很快。这是'queue.Queue'(它是用于线程之间的通信)的基础数据结构。 – Blckknght

+0

有些遗憾的是,'collections.deque'不能被覆盖来覆盖'popleft'(人们猜测会抛出元素),以产生一个元素,然后可以用'maxlen'参数来使用它。 ..然后你会有'mydeque(islice(iterable,None,10),10)'' –