de Python incorporada itertools
módulo en realidad tiene una función groupby
que se puede utilizar, pero los elementos que se agrupan primero deben ser ordenados de tal manera que los elementos a ser agrupados son contiguos en la lista:
sortkeyfn = key=lambda s:s[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 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 dicts donde el 'tipo' es la clave, y 'items' es una lista de los elementos 0'th de las tuplas devueltas por el value_iterator. De esta manera:
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 deseada, como se indica en su pregunta.
Usted podría considerar, sin embargo, hacer una sola frase de esto, teclear por tipo, y cada valor que contiene la lista de valores. En su forma actual, para encontrar los valores para un tipo particular, tendrá que iterar sobre la lista para encontrar el dictado que contiene la tecla correspondiente 'tipo', y luego obtener el elemento 'elementos' de la misma. Si usa un solo dict en lugar de una lista de dictados de 1 ítem, puede encontrar los ítems para un tipo particular con una sola búsqueda por clave en el dict maestro.Usando groupby
, este sería el resultado:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
ahora contiene este dict (esto es similar al intermedio res
defaultdict en 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, se puede:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
o el uso de la forma dict-comprensión de última moda:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
¿Cómo se puede hacer esto si la tupla de entrada tiene una llave y dos o más valores, así: '[('11013331', 'rojo' , 'KAT'), ('9085267', 'azul' 'KAT')] 'donde el último elemento de tupla es la clave y los dos primeros como valor. El resultado debería ser así: resultado = [{ tipo: 'KAT', elementos: [('11013331', rojo), ('9085267', azul)]}] – user1144616