All but the last N elements of iterator in Python
Use a collections.deque
. Push N
items from the source on the first invocation. On each subsequent invocation, pop an item out, push an item in from the source, and yield the popped item.
Just for the fun of it, here's a variation on Ignacio's solution that doesn't require a deque.
>>> def truncate(it, n):
... cache = [next(it) for i in range(n)]
... index = 0
... for val in it:
... val, cache[index] = cache[index], val
... index = (index + 1) % n
... yield val
I wasn't especially concerned with speed when I wrote the above... but perhaps this would be a tad faster:
def truncate(it, n):
cache = [next(it) for i in range(n)]
index = 0
for val in it:
yield cache[index]
cache[index] = val
index = (index + 1) % n
Based on Ignacio Vazquez-Abrams's description:
from collections import deque
def all_but_the_last_n(iterable, count):
q = deque()
i = iter(iterable)
for n in range(count):
q.append(i.next())
for item in i:
q.append(item)
yield q.popleft()
I wondered whether it was better to use the deque right to left (append, popleft) or left to right (appendleft, pop). So i timed it with python 2.5.2 and found that rtl was 3.59 usec
while ltr was 3.53 usec
. The difference of 0.06 usec
is not significant. the test was to append a single item and pop a single item.