Il itertools
modulo integrato di Python ha effettivamente una groupby
funzione, ma per questo gli elementi da raggruppare devono prima essere ordinati in modo tale che gli elementi da raggruppare siano contigui nell'elenco:
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)
Ora l'input ha questo aspetto:
[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),
('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]
groupby
restituisce una sequenza di 2-tuple, della forma (key, values_iterator)
. Quello che vogliamo è trasformare questo in un elenco di dict in cui il "tipo" è la chiave e "elementi" è un elenco degli elementi 0 delle tuple restituite da values_iterator. Come questo:
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)))
Ora result
contiene il dict desiderato, come indicato nella tua domanda.
Potresti considerare, tuttavia, di creare un singolo dict da questo, con chiave per tipo e ogni valore contenente l'elenco di valori. Nella tua forma attuale, per trovare i valori per un particolare tipo, dovrai scorrere l'elenco per trovare il dict contenente la chiave "type" corrispondente, e quindi ottenere l'elemento "items" da esso. Se usi un singolo dict invece di un elenco di dict a 1 elemento, puoi trovare gli elementi per un particolare tipo con una singola ricerca con chiave nel dict principale. Utilizzando groupby
, questo sarebbe simile a:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
ora contiene questo dict (questo è simile al res
defaultdict intermedio nella risposta di @ KennyTM):
{'NOT': ['9085267', '11788544'],
'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'],
'KAT': ['11013331', '9843236']}
(Se vuoi ridurlo a una battuta, puoi:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
o usando il nuovo modulo di comprensione dei dettami:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
[('11013331', 'red', 'KAT'), ('9085267', 'blue' 'KAT')]
dove l'ultimo elemento della tupla è chiave e i primi due come valore. Il risultato dovrebbe essere questo: risultato = [{tipo: 'KAT', elementi: [('11013331', rosso), ('9085267', blu)]}]