Python Language
Itertools-modul
Sök…
Syntax
import itertools
Gruppera objekt från ett iterable objekt med en funktion
Börja med en iterable som måste grupperas
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]
Generera den grupperade generatorn, gruppera efter det andra elementet i varje tupel:
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)]
Endast grupper av på varandra följande element grupperas. Du kanske måste sortera efter samma tangent innan du ringer gruppby för t.ex. (Sista element ändras)
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)]
Gruppen som returneras av groupby är en iterator som kommer att vara ogiltig före nästa iteration. Exempelvis fungerar inte följande om du vill att grupperna ska sorteras efter nyckel. Grupp 5 är tom nedan eftersom när grupp 2 hämtas ogiltigför den 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 []
För att sortera korrekt ska du skapa en lista från iteratorn innan du sorterar
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)]
Ta en skiva av en generator
Itertools "islice" låter dig skära en generator:
results = fetch_paged_results() # returns a generator
limit = 20 # Only want the first 20 results
for data in itertools.islice(results, limit):
print(data)
Normalt kan du inte skära en generator:
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in gen()[:3]:
print(part)
Kommer att ge
Traceback (most recent call last):
File "gen.py", line 6, in <module>
for part in gen()[:3]:
TypeError: 'generator' object is not subscriptable
Men detta fungerar:
import itertools
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in itertools.islice(gen(), 3):
print(part)
Observera att som en vanlig skiva, kan du också använda start
, stop
och step
argument:
itertools.islice(iterable, 1, 30, 3)
itertools.product
Denna funktion låter dig iterera över den kartesiska produkten av en lista med iterables.
Till exempel,
for x, y in itertools.product(xrange(10), xrange(10)):
print x, y
är ekvivalent med
for x in xrange(10):
for y in xrange(10):
print x, y
Liksom alla pythonfunktioner som accepterar ett variabelt antal argument, kan vi skicka en lista till itertools.product för packning, med * -operatören.
Således,
its = [xrange(10)] * 2
for x,y in itertools.product(*its):
print x, y
ger samma resultat som båda de tidigare exemplen.
>>> 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
Introduktion:
Denna enkla funktion genererar oändliga antal serier. Till exempel...
for number in itertools.count():
if number > 20:
break
print(number)
Observera att vi måste bryta eller så skrivs det ut för alltid!
Produktion:
0
1
2
3
4
5
6
7
8
9
10
Argument:
count()
tar två argument, start
och step
:
for number in itertools.count(start=10, step=4):
print(number)
if number > 20:
break
Produktion:
10
14
18
22
itertools.takewhile
itertools.takewhile gör att du kan ta objekt från en sekvens tills ett tillstånd först blir 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)
Denna utgångar [0, 2, 4, 12, 18]
.
Observera att det första numret som bryter mot predikatet (dvs. funktionen som returnerar ett booleskt värde) is_even
är 13
. När takewhile
möter ett värde som producerar False
för det givna predikatet, bryter det ut.
Utgången som produceras av takewhile
liknar den som produceras från koden nedan.
def takewhile(predicate, iterable):
for x in iterable:
if predicate(x):
yield x
else:
break
Obs: Sammanlänkningen av resultat som produceras av takewhile
och dropwhile
ger den ursprungliga iterable.
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
itertools.dropwhile
itertools.dropetime gör att du kan ta objekt från en sekvens efter att ett tillstånd först blev 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)
Denna utgångar [13, 14, 22, 23, 44]
.
(Det här exemplet är samma som exemplet för takewhile
men använder dropwhile
. )
Observera att det första numret som bryter mot predikatet (dvs. funktionen som returnerar ett booleskt värde) is_even
är 13
. Alla element innan detta kasseras.
Utgången som produceras efter dropwhile
liknar den som genereras från koden nedan.
def dropwhile(predicate, iterable):
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x
Sammankopplingen av resultat som produceras av takewhile
och dropwhile
ger den ursprungliga iterable.
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
Dragkedja två iteratorer tills de båda är utmattade
I likhet med den inbyggda funktionen zip()
kommer itertools.zip_longest
att fortsätta att iterera bortom slutet av den kortare av två iterables.
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)
Ett valfritt fillvalue
kan skickas (som standard till ''
) så:
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)
I Python 2.6 och 2.7 kallas den här funktionen itertools.izip_longest
.
Kombinationsmetod i Itertools-modulen
itertools.combinations
kommer att returnera en generator med k- kombinationssekvensen i en lista.
Med andra ord: Det kommer att returnera en generator med tuplar med alla möjliga k-kloka kombinationer av inmatningslistan.
Till exempel:
Om du har en lista:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 2))
print b
Produktion:
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
Ovanstående utgång är en generator omvandlas till en lista med tupler av alla de möjliga par -wise kombinationer av ingångslistan a
Du kan också hitta alla 3-kombinationer:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 3))
print b
Produktion:
[(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)]
Kedja flera iteratorer ihop
Använd itertools.chain
att skapa en enda generator som ger värden från flera generatorer i följd.
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))
Resulterar i:
'1 2 3 4 x y z'
Som en alternativ konstruktör kan du använda klassmetoden chain.from_iterable
som tar sin enda parameter som en iterable av iterables. För att få samma resultat som ovan:
' '.join(chain.from_iterable([a,b])
Medan chain
kan ta ett godtyckligt antal argument, är chain.from_iterable
det enda sättet att kedja ett oändligt antal iterables.
itertools.repeat
Upprepa något n gånger:
>>> import itertools
>>> for i in itertools.repeat('over-and-over', 3):
... print(i)
over-and-over
over-and-over
over-and-over
Få en ackumulerad summa av siffror i en iterable
accumulate
ger en kumulativ summa (eller produkt) av siffror.
>>> 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]
Bläddra igenom element i en iterator
cycle
är en oändlig iterator.
>>> import itertools as it
>>> it.cycle('ABCD')
A B C D A B C D A B C D ...
Var därför noga med att ge gränser när du använder detta för att undvika en oändlig slinga. Exempel:
>>> # 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
returnerar en generator med successiva r-längd permutationer av element i det iterable.
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)]
om listan a
har duplicerade element, kommer de resulterande permutationerna att ha duplikatelement, kan du använda set
att få unika permutationer:
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)}