Use slice notation with collections.deque
How would you extract items 3..6 efficiently, elegantly and pythonically from the following deque
without altering it:
from collections import deque
q = deque('',maxlen=10)
for i in range(10,20):
q.append(i)
the slice notation doesn't seem to work with deque
...
import itertools
output = list(itertools.islice(q, 3, 7))
For example:
>>> import collections, itertools
>>> q = collections.deque(xrange(10, 20))
>>> q
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> list(itertools.islice(q, 3, 7))
[13, 14, 15, 16]
This should be more efficient the the other solutions posted so far. Proof?
[me@home]$ SETUP="import itertools,collections; q=collections.deque(xrange(1000000))"
[me@home]$ python -m timeit "$SETUP" "list(itertools.islice(q, 10000, 20000))"
10 loops, best of 3: 68 msec per loop
[me@home]$ python -m timeit "$SETUP" "[q[i] for i in xrange(10000, 20000)]"
10 loops, best of 3: 98.4 msec per loop
[me@home]$ python -m timeit "$SETUP" "list(q)[10000:20000]"
10 loops, best of 3: 107 msec per loop
I would prefer this, it's shorter so easier to read:
output = list(q)[3:6+1]
This is an old question, but for any future travelers, the Python docs explicitly recommend using rotate
for this:
The rotate() method provides a way to implement deque slicing and deletion.
https://docs.python.org/2/library/collections.html
An implementation is relatively simple:
def slice_deque(d, start, stop, step):
d.rotate(-start)
slice = list(itertools.islice(d, 0, stop-start, step))
d.rotate(start)
return slice
Effectively the same as using islice
directly, except that rotate
is more efficient for skipping through to the starting point. On the other hand, it also temporarily modifies the deque, which could be a threadsafety concern.