Подтвердить что ты не робот

Использовать нотацию фрагмента с помощью collection.deque

Как бы вы извлекали элементы 3..6 эффективно, элегантно и питонически из следующего deque, не изменяя его:

from collections import deque
q = deque('',maxlen=10)
for i in range(10,20):
    q.append(i)

нотация среза, похоже, не работает с deque...

4b9b3361

Ответ 1

import itertools
output = list(itertools.islice(q, 3, 7))

Например:

>>> 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]

Это должно быть более эффективным, чем другие решения, опубликованные до сих пор. Доказательство?

[[email protected]]$ SETUP="import itertools,collections; q=collections.deque(xrange(1000000))"

[[email protected]]$ python -m timeit  "$SETUP" "list(itertools.islice(q, 10000, 20000))"
10 loops, best of 3: 68 msec per loop

[[email protected]]$ python -m timeit "$SETUP" "[q[i] for i in  xrange(10000, 20000)]"
10 loops, best of 3: 98.4 msec per loop

[[email protected]]$ python -m timeit "$SETUP" "list(q)[10000:20000]"
10 loops, best of 3: 107 msec per loop

Ответ 2

output = [q[i] for i in range(3,6+1)]

Ответ 3

Я бы предпочел это, это было бы короче, так легче читать:

output = list(q)[3:6+1]

Ответ 4

Я бы добавил это как новый ответ, чтобы обеспечить лучшее форматирование.

Для простоты ответ Shawn идеален, но если вам часто нужно получить фрагмент из dequeue, вы можете захотеть подклассифицировать его и добавить метод __getslice__.

from collections import deque
from itertools import islice
class deque_slice(deque):
    def __new__(cls, *args):
        return deque.__new__(cls, *args)
    def __getslice__(self, start, end):
        return list(islice(self, start, end))

Это не будет поддерживать настройку нового среза, но вы можете реализовать свой собственный метод __setslice__, используя ту же концепцию.

Ответ 5

Вы можете переопределить метод __getitem__ и создать SliceableDeque с помощью islice.

Есть крайние случаи, которые вы должны рассмотреть (например, использование отрицательных срезов не работает с islice).

вот что я использовал:

import itertools
from collections import deque

class SliceableDeque(deque):
    def __getitem__(self, s):
        try:
            start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1
        except AttributeError:  # not a slice but an int
            return super().__getitem__(s)
        else:
            try:
                return list(itertools.islice(self, start, stop, step))
            except ValueError:  # iscase of a negative slice objects
                length = len(self)
                start, stop = length + start if start < 0 else start, length + stop if stop < 0 else stop
                return list(itertools.islice(self, start, stop, step))