2011-08-15 13 views

Odpowiedz

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

Na przykład:

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

ten powinien być bardziej efektywny gdy inne rozwiązania pisał do tej pory. Dowód?

[[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 
+0

Bardzo ładne. Ponieważ masz pełny przykład, być może 'q.extend (zakres (10, 20))' może być lepszy. –

+0

@rm tak, 'q.extend (..)' byłoby dobrze. W rzeczywistości należy użyć 'q = deque (xrange (10,20))'. Po prostu skopiowałem przykład OP, tak jak jest. Zaktualizowana odpowiedź. –

1

wolałbym to, to krótszy więc łatwiejsze do odczytania:

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

Ale tworzy dwie kopie "deque" (jedna pełna, jedna cząstkowa) zamiast jednej częściowej kopii. Nie ma problemu, jeśli 'deque' jest krótki, ale może być, jeśli jest długi. – agf

+0

To prawda. Ale tak naprawdę nie jest to przypadek użycia "deque". Drugie rozwiązanie tworzy listę dla 'zakresu'. Pomyślałbym o tym jak o 'list (set (list))' hack'u, aby znaleźć unikalne elementy listy - eleganckie i ładne, ale może nie najskuteczniejsze. –

+0

Można tylko podstawić 'xrange' dla zakresu i nie tworzyłoby to listy - również, rozważ jeśli chcesz krótki kawałek długiej' deque' - lista częściowa i/lub zakres byłyby małe, ale pełna kopia stanowiłaby problem. – agf

1

Dodałbym to jako nową odpowiedź, aby zapewnić lepsze formatowanie.

Dla uproszczenia odpowiedź Shawna jest idealna, ale jeśli często potrzebujemy uzyskać plasterek od dequeue, można preferować podklasę i dodać metodę __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)) 

To nie będzie wspierać ustawienie nowy kawałek, ale można zaimplementować własną zwyczaj __setslice__ metodę przy użyciu tej samej koncepcji.