Python Language
Modulo Itertools
Ricerca…
Sintassi
import itertools
Raggruppamento di elementi da un oggetto iterabile mediante una funzione
Inizia con un iterabile che deve essere raggruppato
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]
Genera il generatore raggruppato, raggruppando il secondo elemento in ciascuna tupla:
def testGroupBy(lst):
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in groups:
print(key, list(group))
testGroupBy(lst)
# 5 [('a', 5, 6)]
# 2 [('b', 2, 4), ('a', 2, 5), ('c', 2, 6)]
Solo i gruppi di elementi consecutivi sono raggruppati. Potrebbe essere necessario ordinare la stessa chiave prima di chiamare groupby Per Eg, (L'ultimo elemento è cambiato)
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 5, 6)]
testGroupBy(lst)
# 5 [('a', 5, 6)]
# 2 [('b', 2, 4), ('a', 2, 5)]
# 5 [('c', 5, 6)]
Il gruppo restituito da groupby è un iteratore che non sarà valido prima della prossima iterazione. Ad esempio il seguente non funzionerà se si desidera che i gruppi siano ordinati per chiave. Il gruppo 5 è vuoto sotto perché quando viene recuperato il gruppo 2 invalida 5
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in sorted(groups):
print(key, list(group))
# 2 [('c', 2, 6)]
# 5 []
Per eseguire correttamente l'ordinamento, creare un elenco dall'iteratore prima di ordinare
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in sorted((key, list(group)) for key, group in groups):
print(key, list(group))
# 2 [('b', 2, 4), ('a', 2, 5), ('c', 2, 6)]
# 5 [('a', 5, 6)]
Prendi una fetta di un generatore
Itertools "islice" ti permette di tagliare un generatore:
results = fetch_paged_results() # returns a generator
limit = 20 # Only want the first 20 results
for data in itertools.islice(results, limit):
print(data)
Normalmente non puoi tagliare un generatore:
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in gen()[:3]:
print(part)
Darà
Traceback (most recent call last):
File "gen.py", line 6, in <module>
for part in gen()[:3]:
TypeError: 'generator' object is not subscriptable
Tuttavia, questo funziona:
import itertools
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in itertools.islice(gen(), 3):
print(part)
Tieni presente che, come una normale slice, puoi anche utilizzare gli argomenti start
, stop
e step
:
itertools.islice(iterable, 1, 30, 3)
itertools.product
Questa funzione consente di scorrere il prodotto cartesiano di un elenco di iterabili.
Per esempio,
for x, y in itertools.product(xrange(10), xrange(10)):
print x, y
è equivalente a
for x in xrange(10):
for y in xrange(10):
print x, y
Come tutte le funzioni python che accettano un numero variabile di argomenti, possiamo passare una lista a itertools.product per decomprimere, con l'operatore *.
Così,
its = [xrange(10)] * 2
for x,y in itertools.product(*its):
print x, y
produce gli stessi risultati di entrambi gli esempi precedenti.
>>> from itertools import product
>>> a=[1,2,3,4]
>>> b=['a','b','c']
>>> product(a,b)
<itertools.product object at 0x0000000002712F78>
>>> for i in product(a,b):
... print i
...
(1, 'a')
(1, 'b')
(1, 'c')
(2, 'a')
(2, 'b')
(2, 'c')
(3, 'a')
(3, 'b')
(3, 'c')
(4, 'a')
(4, 'b')
(4, 'c')
itertools.count
Introduzione:
Questa semplice funzione genera serie infinite di numeri. Per esempio...
for number in itertools.count():
if number > 20:
break
print(number)
Nota che dobbiamo rompere o stampare per sempre!
Produzione:
0
1
2
3
4
5
6
7
8
9
10
Argomenti:
count()
accetta due argomenti, start
e step
:
for number in itertools.count(start=10, step=4):
print(number)
if number > 20:
break
Produzione:
10
14
18
22
itertools.takewhile
itertools.takewhile consente di prendere elementi da una sequenza finché una condizione non diventa False
.
def is_even(x):
return x % 2 == 0
lst = [0, 2, 4, 12, 18, 13, 14, 22, 23, 44]
result = list(itertools.takewhile(is_even, lst))
print(result)
Questo produce [0, 2, 4, 12, 18]
.
Nota che, il primo numero che viola il predicato (es: la funzione che restituisce un valore booleano) is_even
è, 13
. Una volta che takewhile
incontra un valore che produce False
per il predicato specificato, esso scoppia.
L' output prodotto da takewhile
è simile all'output generato dal codice sottostante.
def takewhile(predicate, iterable):
for x in iterable:
if predicate(x):
yield x
else:
break
Nota: la concatenazione dei risultati prodotti da takewhile
e dropwhile
produce l'originale iterabile.
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
itertools.dropwhile
itertools.dropwhile consente di prelevare elementi da una sequenza dopo che una condizione diventa False
.
def is_even(x):
return x % 2 == 0
lst = [0, 2, 4, 12, 18, 13, 14, 22, 23, 44]
result = list(itertools.dropwhile(is_even, lst))
print(result)
Questo produce [13, 14, 22, 23, 44]
.
( Questo esempio è lo stesso dell'esempio per takewhile
ma usando dropwhile
. )
Nota che, il primo numero che viola il predicato (es: la funzione che restituisce un valore booleano) is_even
è, 13
. Tutti gli elementi prima di questo vengono scartati.
L' output prodotto da dropwhile
è simile all'output generato dal codice seguente.
def dropwhile(predicate, iterable):
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x
La concatenazione dei risultati prodotti da takewhile
e dropwhile
produce l'originale iterabile.
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
Zippare due iteratori finché non sono entrambi esauriti
Simile alla funzione built-in zip()
, itertools.zip_longest
continuerà a itertools.zip_longest
oltre la fine del più breve di due iterabili.
from itertools import zip_longest
a = [i for i in range(5)] # Length is 5
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] # Length is 7
for i in zip_longest(a, b):
x, y = i # Note that zip longest returns the values as a tuple
print(x, y)
È possibile fillvalue
argomento fillvalue
facoltativo (predefinito su ''
) in questo modo:
for i in zip_longest(a, b, fillvalue='Hogwash!'):
x, y = i # Note that zip longest returns the values as a tuple
print(x, y)
In Python 2.6 e 2.7, questa funzione è chiamata itertools.izip_longest
.
Metodo di combinazioni nel modulo Itertools
itertools.combinations
restituirà un generatore della sequenza k -combination di una lista.
In altre parole: restituirà un generatore di tuple di tutte le possibili combinazioni di k dell'elenco di input.
Per esempio:
Se hai una lista:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 2))
print b
Produzione:
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
L'uscita di cui sopra è un generatore convertito in una lista di tuple tutte le possibili combinazioni di coppia -wise lista di input a
Puoi anche trovare tutte le 3 combinazioni:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 3))
print b
Produzione:
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4),
(1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5),
(2, 4, 5), (3, 4, 5)]
Concatenare più iteratori insieme
Utilizzare itertools.chain
per creare un singolo generatore che fornirà in sequenza i valori di diversi generatori.
from itertools import chain
a = (x for x in ['1', '2', '3', '4'])
b = (x for x in ['x', 'y', 'z'])
' '.join(chain(a, b))
Risultati in:
'1 2 3 4 x y z'
Come costruttore alternativo, puoi usare il metodo chain.from_iterable
che prende come parametro singolo un iterabile di iterabili. Per ottenere lo stesso risultato di cui sopra:
' '.join(chain.from_iterable([a,b])
Mentre chain
può assumere un numero arbitrario di argomenti, chain.from_iterable
è l'unico modo per concatenare un numero infinito di iterabili.
itertools.repeat
Ripeti qualcosa n volte:
>>> import itertools
>>> for i in itertools.repeat('over-and-over', 3):
... print(i)
over-and-over
over-and-over
over-and-over
Ottieni una somma cumulativa di numeri in un iterabile
accumulate
produce una somma cumulativa (o un prodotto) di numeri.
>>> import itertools as it
>>> import operator
>>> list(it.accumulate([1,2,3,4,5]))
[1, 3, 6, 10, 15]
>>> list(it.accumulate([1,2,3,4,5], func=operator.mul))
[1, 2, 6, 24, 120]
Passa attraverso gli elementi in un iteratore
cycle
è un iteratore infinito.
>>> import itertools as it
>>> it.cycle('ABCD')
A B C D A B C D A B C D ...
Pertanto, fai attenzione a dare dei limiti quando usi questo per evitare un ciclo infinito. Esempio:
>>> # Iterate over each element in cycle for a fixed range
>>> cycle_iterator = it.cycle('abc123')
>>> [next(cycle_iterator) for i in range(0, 10)]
['a', 'b', 'c', '1', '2', '3', 'a', 'b', 'c', '1']
itertools.permutations
itertools.permutations
restituisce un generatore con permutazioni di lunghezza-lunghezza successive di elementi nel iterabile.
a = [1,2,3]
list(itertools.permutations(a))
# [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
list(itertools.permutations(a, 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
se l'elenco a
ha elementi duplicati, le permutazioni risultanti avranno elementi duplicati, è possibile utilizzare set
per ottenere permute uniche:
a = [1,2,1]
list(itertools.permutations(a))
# [(1, 2, 1), (1, 1, 2), (2, 1, 1), (2, 1, 1), (1, 1, 2), (1, 2, 1)]
set(itertools.permutations(a))
# {(1, 1, 2), (1, 2, 1), (2, 1, 1)}