¿Cómo uso itertools.groupby()?

Resuelto James Sulak asked hace 16 años • 15 respuestas

No he podido encontrar una explicación comprensible de cómo utilizar realmente la itertools.groupby()función de Python. Lo que estoy tratando de hacer es esto:

  • Tome una lista; en este caso, los hijos de un lxmlelemento objetivado.
  • Dividirlo en grupos según algunos criterios.
  • Luego, repita cada uno de estos grupos por separado.

Revisé la documentación , pero tuve problemas al intentar aplicarla más allá de una simple lista de números.

Entonces, ¿cómo uso itertools.groupby()? ¿Hay otra técnica que debería utilizar? También se agradecerían sugerencias sobre una buena lectura como "requisito previo".

James Sulak avatar Aug 04 '08 01:08 James Sulak
Aceptado

NOTA IMPORTANTE: Es posible que primero tengas que ordenar tus datos .


La parte que no entendí es que en la construcción del ejemplo.

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

kes la clave de agrupación actual y ges un iterador que puede utilizar para iterar sobre el grupo definido por esa clave de agrupación. En otras palabras, el groupbypropio iterador devuelve iteradores.

Aquí hay un ejemplo de eso, usando nombres de variables más claros:

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

Esto le dará el resultado:

Un oso es un animal.
Un pato es un animal.

Un cactus es una planta.

Una lancha rápida es un vehículo.
Un autobús escolar es un vehículo.

En este ejemplo, thingshay una lista de tuplas donde el primer elemento de cada tupla es el grupo al que pertenece el segundo elemento.

La groupby()función toma dos argumentos: (1) los datos a agrupar y (2) la función con la que agruparlos.

Aquí, lambda x: x[0]se indica groupby()que se utilice el primer elemento de cada tupla como clave de agrupación.

En la fordeclaración anterior, groupbydevuelve tres pares (clave, iterador de grupo), una vez para cada clave única. Puede utilizar el iterador devuelto para iterar sobre cada elemento individual de ese grupo.

Aquí hay un ejemplo ligeramente diferente con los mismos datos, usando una lista por comprensión:

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

Esto le dará el resultado:

animales: oso y pato.
plantas: cactus.
Vehículos: lancha rápida y autobús escolar.

James Sulak avatar Aug 10 '2008 18:08 James Sulak

itertools.groupbyes una herramienta para agrupar elementos.

De los documentos , obtenemos más información sobre lo que podría hacer:

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B

# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D

groupbyLos objetos producen pares clave-grupo donde el grupo es un generador.

Características

  • A. Agrupar elementos consecutivos
  • B. Agrupar todas las apariciones de un elemento, dado un iterable ordenado
  • C. Especificar cómo agrupar elementos con una función clave *

Comparaciones

# Define a printer for comparing outputs
>>> def print_groupby(iterable, keyfunc=None):
...    for k, g in it.groupby(iterable, keyfunc):
...        print("key: '{}'--> group: {}".format(k, list(g)))
# Feature A: group consecutive occurrences
>>> print_groupby("BCAACACAADBBB")
key: 'B'--> group: ['B']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A']
key: 'C'--> group: ['C']
key: 'A'--> group: ['A', 'A']
key: 'D'--> group: ['D']
key: 'B'--> group: ['B', 'B', 'B']

# Feature B: group all occurrences
>>> print_groupby(sorted("BCAACACAADBBB"))
key: 'A'--> group: ['A', 'A', 'A', 'A', 'A']
key: 'B'--> group: ['B', 'B', 'B', 'B']
key: 'C'--> group: ['C', 'C', 'C']
key: 'D'--> group: ['D']

# Feature C: group by a key function
>>> # islower = lambda s: s.islower()                      # equivalent
>>> def islower(s):
...     """Return True if a string is lowercase, else False."""   
...     return s.islower()
>>> print_groupby(sorted("bCAaCacAADBbB"), keyfunc=islower)
key: 'False'--> group: ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'D']
key: 'True'--> group: ['a', 'a', 'b', 'b', 'c']

Usos

  • Anagramas ( ver cuaderno )
  • Binning
  • Agrupar números pares e impares
  • Agrupar una lista por valores
  • Eliminar elementos duplicados
  • Encuentra índices de elementos repetidos en una matriz.
  • Dividir una matriz en fragmentos de tamaño n
  • Encuentra elementos correspondientes entre dos listas.
  • Algoritmo de compresión ( ver cuaderno )/ Codificación de longitud de ejecución
  • Agrupar letras por longitud, función clave ( ver cuaderno )
  • Valores consecutivos por encima de un umbral ( ver cuaderno )
  • Find ranges of numbers in a list or continuous items (see docs)
  • Find all related longest sequences
  • Take consecutive sequences that meet a condition (see related post)

Note: Several of the latter examples derive from Víctor Terrón's PyCon (talk) (Spanish), "Kung Fu at Dawn with Itertools". See also the groupby source code written in C.

* A function where all items are passed through and compared, influencing the result. Other objects with key functions include sorted(), max() and min().


Response

# OP: Yes, you can use `groupby`, e.g. 
[do_something(list(g)) for _, g in groupby(lxml_elements, criteria_func)]
pylang avatar Aug 25 '2017 02:08 pylang