672 votes

Comment utiliser Python ' s itertools.groupby() ?

Je n'ai pas été en mesure de trouver une explication compréhensible de la façon dont utiliser Python itertools.groupby() fonction. Ce que j'essaie de faire est ceci:

  • Prendre une liste - dans ce cas, les enfants d'un objectivé lxml élément
  • La diviser en groupes en fonction de certains critères
  • Puis, plus tard itérer sur chaque de ces groupes séparément.

J'ai passé en revue la documentationet les exemples, mais j'ai eu du mal à essayer de les appliquer au-delà d'une simple liste de nombres.

Alors, comment puis-je utiliser de l' itertools.groupby()? Est-il une autre technique que je devrais utiliser? Pistes pour une bonne "condition préalable" de la lecture serait également appréciée.

844voto

James Sulak Points 9959

Après quelques essais, j'ai surmonté ma blocage mental. En rétrospective, il est tout évident, mais dans l'esprit de Dépassement de Pile, voici ce que j'ai appris.

Comme Sebastjan dit, *tout d'abord vous devez trier vos données. Ce qui est important.*

La partie que je n'ai pas l'obtenir, c'est que dans l'exemple de la construction

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
   groups.append(list(g))    # Store group iterator as a list
   uniquekeys.append(k)

"k" est le regroupement actuel de la clé, et "g" est un itérateur que vous pouvez utiliser pour effectuer une itération sur le groupe, défini par le fait que le regroupement de la clé. En d'autres termes, le groupby itérateur lui-même renvoie les itérateurs. Voici un exemple, en utilisant plus clair les noms de variables:

from itertools import groupby

things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]

for key, group in groupby(things, lambda x: x[0]):
    for thing in group:
        print "A %s is a %s." % (thing[1], key)
    print " "

Cela vous donnera le résultat:

Un ours est un animal.
Un canard est un animal.

Un cactus est une plante.

Un bateau à moteur est un véhicule.
Un autobus est un véhicule.

Dans cet exemple, les "choses" est une liste de tuples où le premier élément de chaque tuple est le groupe le deuxième élément appartient. La fonction groupby() prend deux arguments: (1) les données de groupe et (2) la fonction de groupe. Ici, "lambda x: x[0]," raconte l'groupby() pour utiliser le premier élément de chaque tuple comme le regroupement de la clé.

Dans l'au-delà "pour" déclaration, groupby retourne trois (clé, groupe itérateur) paires - une fois pour chaque clé unique. Vous pouvez utiliser le retour de l'itérateur pour parcourir chaque élément individuel que de groupe.

Voici un exemple légèrement différent avec les mêmes données, à l'aide d'une compréhension de liste:

for key, group in groupby(things, lambda x: x[0]):
    listOfThings = " and ".join(["%s" % thing[1] for thing in group])
    print key + "s:  " + listOfThings + "."

Cela vous donnera le résultat:

animaux: l'ours et le canard.
plantes: cactus.
véhicules: vitesse du bateau et de bus d'école.

Python est plutôt cool, non?

75voto

Seb Points 5120

Pouvez-vous nous montrer votre code?

L'exemple sur les docs Python est assez simple:

 groups = [] 

Donc dans votre cas, les données sont une liste de nœuds, keyfunc est l'endroit où va la logique de votre fonction de critères, puis groupby () groupe les données. Vous devez faire attention à trier les données selon les critères avant d'appeler groupby ou cela ne fonctionnera pas. En réalité, la méthode groupby ne fait que répéter une liste et chaque fois que la clé change, elle crée un nouveau groupe.

51voto

nimish Points 1070

Un truc génial avec groupby est d'exécuter un encodage de longueur sur une ligne:

 [(c,len(list(cgen))) for c,cgen in groupby(some_string)]
 

vous donnera une liste de 2-tuples où le premier élément est le char et le 2ème est le nombre de répétitions.

34voto

user650654 Points 588

Un autre exemple:

for key, igroup in itertools.groupby(xrange(12), lambda x: x // 5):
    print key, list(igroup)

résultats dans

0 [0, 1, 2, 3, 4]
1 [5, 6, 7, 8, 9]
2 [10, 11]

Notez que igroup n'est un itérateur (un sous-itérateur comme la documentation des appels).

Ceci est utile pour la segmentation d'un générateur:

def chunker(items, chunk_size):
    '''Group items in chunks of chunk_size'''
    for _key, group in itertools.groupby(enumerate(items), lambda x: x[0] // chunk_size):
        yield (g[1] for g in group)

with open('file.txt') as fobj:
    for chunk in chunker(fobj):
        process(chunk)

Un autre exemple de groupby - lorsque les touches ne sont pas triés. Dans l'exemple suivant, les éléments du xx sont groupées par valeurs dans aa. Dans ce cas, un ensemble de zéros est sortie en premier, suivi par un ensemble de celles, suivi de nouveau par un ensemble de zéros.

xx = range(10)
yy = [0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
for group in itertools.groupby(iter(xx), lambda x: yy[x]):
    print group[0], list(group[1])

Produit:

0 [0, 1, 2]
1 [3, 4, 5]
0 [6, 7, 8, 9]

24voto

singular Points 508

ATTENTION:

La liste de syntaxe (groupby (...)) ne fonctionnera pas comme vous le souhaitez. Il semble détruire les objets de l'itérateur interne, donc en utilisant

 for x in list(groupby(range(10))):
    print list(x[1])
 

produira:

 []
[]
[]
[]
[]
[]
[]
[]
[]
[9]
 

Au lieu de list (groupby (...)), essayez [k, list (g) pour k, g dans groupby (...)], ou si vous utilisez souvent cette syntaxe,

 def groupbylist(*args, **kwargs):
    return [k, list(g) for k, g in groupby(*args, **kwargs)]
 

et avoir accès à la fonctionnalité groupby tout en évitant ces satanés (pour les petites données) itératreurs tous ensemble.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X