O itertools
módulo interno do Python realmente tem uma groupby
função, mas para que os elementos a serem agrupados sejam primeiro classificados, de modo que os elementos a serem agrupados sejam contíguos na 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)
Agora, a entrada se parece com:
[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),
('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]
groupby
retorna uma sequência de 2 tuplas, do formulário (key, values_iterator)
. O que queremos é transformar isso em uma lista de dictos onde o 'tipo' é a chave e 'itens' é uma lista dos 0'ésimos elementos das tuplas retornadas pelo values_iterator. Como isso:
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)))
Agora result
contém o ditado desejado, conforme indicado na sua pergunta.
Você pode considerar, no entanto, criar um único ditado, digitado por tipo e cada valor contendo a lista de valores. Em seu formulário atual, para encontrar os valores para um tipo específico, você precisará percorrer a lista para encontrar o ditado que contém a chave 'type' correspondente e, em seguida, obter o elemento 'items'. Se você usar um único ditado em vez de uma lista de ditados de 1 item, poderá encontrar os itens para um tipo específico com uma única pesquisa com chave no ditado mestre. Usando groupby
, seria assim:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
agora contém este ditado (é semelhante ao res
padrão intermediário na resposta do @ KennyTM):
{'NOT': ['9085267', '11788544'],
'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'],
'KAT': ['11013331', '9843236']}
(Se você deseja reduzir isso para uma linha, você pode:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
ou usando o novo formulário de compreensão de ditados:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
[('11013331', 'red', 'KAT'), ('9085267', 'blue' 'KAT')]
onde o último elemento da tupla é a chave e os dois primeiros como valor. O resultado deve ser assim: result = [{type: 'KAT', itens: [('11013331', vermelho), ('9085267', azul)])]]