Le itertools
module intégré de Python a en fait une groupby
fonction, mais pour cela les éléments à grouper doivent d'abord être triés de telle sorte que les éléments à grouper soient contigus dans la liste:
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)
Maintenant, l'entrée ressemble à:
[('5238761', 'ETH'), ('5349618', 'ETH'), ('962142', 'ETH'), ('7795297', 'ETH'),
('7341464', 'ETH'), ('5594916', 'ETH'), ('1550003', 'ETH'), ('11013331', 'KAT'),
('9843236', 'KAT'), ('9085267', 'NOT'), ('11788544', 'NOT')]
groupby
renvoie une séquence de 2-tuples, de la forme (key, values_iterator)
. Ce que nous voulons, c'est transformer cela en une liste de dictionnaires où le 'type' est la clé, et 'items' est une liste des 0 'éléments des tuples retournés par le values_iterator. Comme ça:
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)))
result
Contient maintenant votre dict souhaité, comme indiqué dans votre question.
Vous pouvez cependant envisager de créer un seul dict à partir de cela, indexé par type, et chaque valeur contenant la liste de valeurs. Dans votre formulaire actuel, pour trouver les valeurs d'un type particulier, vous devrez parcourir la liste pour trouver le dict contenant la clé 'type' correspondante, puis en extraire l'élément 'items'. Si vous utilisez un seul dict au lieu d'une liste de dictés à 1 élément, vous pouvez trouver les éléments d'un type particulier avec une seule recherche à clé dans le dict maître. En utilisant groupby
, cela ressemblerait à:
result = {}
for key,valuesiter in groupby(input, key=sortkeyfn):
result[key] = list(v[0] for v in valuesiter)
result
contient maintenant ce dict (c'est similaire au res
defaultdict intermédiaire dans la réponse de @ KennyTM):
{'NOT': ['9085267', '11788544'],
'ETH': ['5238761', '5349618', '962142', '7795297', '7341464', '5594916', '1550003'],
'KAT': ['11013331', '9843236']}
(Si vous souhaitez réduire cela à une seule ligne, vous pouvez:
result = dict((key,list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn))
ou en utilisant le nouveau formulaire de compréhension de dict:
result = {key:list(v[0] for v in valuesiter)
for key,valuesiter in groupby(input, key=sortkeyfn)}
[('11013331', 'red', 'KAT'), ('9085267', 'blue' 'KAT')]
où le dernier élément du tuple est la clé et les deux premiers comme valeur. Le résultat devrait ressembler à ceci: result = [{type: 'KAT', items: [('11013331', red), ('9085267', blue)]}]