El itertools
módulo integrado de Python en realidad tiene una groupby
función, pero para eso los elementos que se van a agrupar primero deben ordenarse de manera que los elementos que se agrupen sean contiguos en la lista:
from operator import itemgetter
sortkeyfn = itemgetter(1)
input = [('11013331', 'KAT'), ('9085267', 'NOT'), ('5238761', 'ETH'),
('5349618', 'ETH'), ('11788544', 'NOT'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('9843236', 'KAT'), ('5594916', 'ETH'), ('1550003', 'ETH')]
input.sort(key=sortkeyfn)
Ahora la entrada se ve así:
[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),
('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]
groupby
devuelve una secuencia de 2 tuplas, de la forma (key, values_iterator)
. Lo que queremos es convertir esto en una lista de dictados donde el "tipo" es la clave, y "elementos" es una lista de los elementos número 0 de las tuplas devueltas por el valor_iterador. Me gusta esto:
from itertools import groupby
result = []
for key,valuesiter in groupby(input, key=sortkeyfn):
result.append(dict(type=key, items=list(v[0] for v in valuesiter)))
Ahora result
contiene su dict deseado, como se indica en su pregunta.
Sin embargo, puede considerar hacer un solo resumen de esto, tecleado por tipo, y cada valor que contenga la lista de valores. En su forma actual, para encontrar los valores de un tipo en particular, deberá iterar sobre la lista para encontrar el dict que contiene la clave correspondiente 'tipo' y luego obtener el elemento 'elementos' de él. Si usa un solo dict en lugar de una lista de dictados de 1 elemento, puede encontrar los elementos para un tipo particular con una sola búsqueda con clave en el dict maestro. Usando groupby
, esto se vería así:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
ahora contiene este dict (es similar al res
defaultdictdict intermedio en la respuesta de @ KennyTM)
{'NOT': ['9085267', '11788544'],
'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'],
'KAT': ['11013331', '9843236']}
(Si desea reducir esto a una sola línea, puede:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
o usando la nueva forma de comprensión dict:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
[('11013331', 'red', 'KAT'), ('9085267', 'blue' 'KAT')]
donde el último elemento de la tupla es clave y los dos primeros como valor? El resultado debería ser así: resultado = [{tipo: 'KAT', elementos: [('11013331', rojo), ('9085267', azul)]}]