Recherche…


Syntaxe

  • import itertools

Regroupement d'éléments à partir d'un objet pouvant être itéré à l'aide d'une fonction

Commencez avec une itération qui doit être regroupée

lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]

Générer le générateur groupé, regroupé par le deuxième élément de chaque tuple:

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

Seuls les groupes d'éléments consécutifs sont regroupés. Vous devrez peut-être trier par la même clé avant d'appeler groupby For Eg (le dernier élément est modifié)

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

Le groupe renvoyé par groupby est un itérateur qui sera invalide avant la prochaine itération. Par exemple, les éléments suivants ne fonctionneront pas si vous souhaitez que les groupes soient triés par clé. Le groupe 5 est vide ci-dessous car lorsque le groupe 2 est récupéré, il invalide 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 []

Pour effectuer correctement le tri, créez une liste à partir de l'itérateur avant de trier

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

Prendre une tranche de générateur

Itertools "islice" vous permet de découper un générateur:

results = fetch_paged_results()  # returns a generator
limit = 20  # Only want the first 20 results
for data in itertools.islice(results, limit):
    print(data)

Normalement, vous ne pouvez pas découper un générateur:

def gen():
    n = 0
    while n < 20:
        n += 1
        yield n

for part in gen()[:3]:
    print(part)

Va donner

Traceback (most recent call last):
  File "gen.py", line 6, in <module>
    for part in gen()[:3]:
TypeError: 'generator' object is not subscriptable

Cependant, cela fonctionne:

import itertools

def gen():
    n = 0
    while n < 20:
        n += 1
        yield n

for part in itertools.islice(gen(), 3):
    print(part)

Notez que, comme une tranche normale, vous pouvez également utiliser les arguments start , stop et step :

itertools.islice(iterable, 1, 30, 3)

itertools.product

Cette fonction vous permet de parcourir le produit cartésien d'une liste d'itérables.

Par exemple,

for x, y in itertools.product(xrange(10), xrange(10)):
    print x, y

est équivalent à

for x in xrange(10):
    for y in xrange(10):
        print x, y

Comme toutes les fonctions python acceptant un nombre variable d'arguments, nous pouvons passer une liste à itertools.product pour le décompresser, avec l'opérateur *.

Ainsi,

its = [xrange(10)] * 2
for x,y in itertools.product(*its):
    print x, y

produit les mêmes résultats que les deux exemples précédents.

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

Introduction:

Cette fonction simple génère une série infinie de nombres. Par exemple...

for number in itertools.count():
    if number > 20:
        break
    print(number)

Notez que nous devons casser ou imprimer pour toujours!

Sortie:

0
1
2
3
4
5
6
7
8
9
10

Arguments:

count() prend deux arguments, start et step :

for number in itertools.count(start=10, step=4):
    print(number)
    if number > 20:
        break

Sortie:

10
14
18
22

itertools.takewhile

itertools.takewhile vous permet de prendre des éléments d'une séquence jusqu'à ce qu'une condition devienne la première 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)
  

Cette sortie [0, 2, 4, 12, 18] .

Notez que le premier nombre qui viole le prédicat (c'est-à-dire la fonction renvoyant une valeur booléenne) is_even est 13 . Une fois que takewhile rencontre une valeur qui produit False pour le prédicat donné, elle éclate.

La sortie produite par takewhile est similaire à la sortie générée par le code ci-dessous.

def takewhile(predicate, iterable):
    for x in iterable:
        if predicate(x):
            yield x
        else:
            break

Note: La concaténation des résultats produits par takewhile et dropwhile produit l'itérable original.

result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))

itertools.dropwhile

itertools.dropwhile vous permet de prendre des éléments d'une séquence après qu'une condition soit devenue la première 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)
  

Cette sortie [13, 14, 22, 23, 44] .

( Cet exemple est identique à l'exemple de takewhile mais en utilisant dropwhile . )

Notez que le premier nombre qui viole le prédicat (c'est-à-dire la fonction renvoyant une valeur booléenne) is_even est 13 . Tous les éléments avant cela sont éliminés.

La sortie produite par dropwhile est similaire à la sortie générée par le code ci-dessous.

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 concaténation des résultats produits par takewhile et dropwhile produit l'itérable original.

result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))

Zipper deux itérateurs jusqu'à ce qu'ils soient tous deux épuisés

Semblable à la fonction intégrée zip() , itertools.zip_longest continuera à itérer au-delà de la plus courte des deux itérables.

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)

Un argument facultatif fillvalue peut être passé (par défaut à '' ) comme ceci:

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)

Dans Python 2.6 et 2.7, cette fonction s'appelle itertools.izip_longest .

Méthode des combinaisons dans le module Itertools

itertools.combinations retournera un générateur de la séquence de combinaison k d'une liste.

En d'autres termes: il renverra un générateur de tuples de toutes les combinaisons possibles en k de la liste d'entrée.

Par exemple:

Si vous avez une liste:

a = [1,2,3,4,5]
b = list(itertools.combinations(a, 2))
print b

Sortie:

[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

La sortie ci - dessus est un générateur converti en une liste d'uplets de l' ensemble de la paire possible -wise combinaisons de la liste d'entrée d' a

Vous pouvez également trouver toutes les 3 combinaisons:

a = [1,2,3,4,5]
b = list(itertools.combinations(a, 3))
print b

Sortie:

[(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)]

Enchaînement multiple d'itérateurs

Utilisez itertools.chain pour créer un seul générateur qui produira les valeurs de plusieurs générateurs en séquence.

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

Résulte en:

'1 2 3 4 x y z'

En tant que constructeur alternatif, vous pouvez utiliser classmethod chain.from_iterable qui prend comme paramètre unique une itération d'itérables. Pour obtenir le même résultat que ci-dessus:

' '.join(chain.from_iterable([a,b])

Alors que la chain peut prendre un nombre arbitraire d'arguments, chain.from_iterable est le seul moyen de chaîner un nombre infini d'itérables.

itertools.reat

Répétez quelque chose n fois:

>>> import itertools
>>> for i in itertools.repeat('over-and-over', 3):
...    print(i)
over-and-over
over-and-over
over-and-over

Obtenir une somme cumulée de nombres dans une itération

Python 3.x 3.2

accumulate donne une somme (ou un produit) cumulatif de nombres.

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

Parcourir des éléments dans un itérateur

cycle est un itérateur infini.

>>> import itertools as it
>>> it.cycle('ABCD')
A B C D A B C D A B C D ...

Par conséquent, veillez à donner des limites lorsque vous utilisez ceci pour éviter une boucle infinie. Exemple:

>>> # 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 renvoie un générateur avec des permutations successives de longueur r d'éléments dans l'itérable.

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

si la liste a comporte des éléments en double, les permutations résultants ont des éléments en double, vous pouvez utiliser set pour obtenir des permutations uniques:

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)}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow