web-dev-qa-db-fra.com

conversion de liste en dictionnaire avec plusieurs valeurs par clé?

J'ai une liste Python qui contient des paires clé/valeur:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]

Je veux convertir la liste en dictionnaire, où plusieurs valeurs par clé seraient agrégées en un tuple:

{ 1:('A', 'B'), 2:('C',) }

La solution itérative est triviale:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
d={}
for pair in l:
    if d.has_key(pair[0]):
        d[pair[0]]=d[pair[0]]+Tuple(pair[1])
    else:
        d[pair[0]]=Tuple(pair[1])

print d

{1: ('A', 'B'), 2: ('C',)}

Existe-t-il une solution Pythonic plus élégante pour cette tâche?

52
Adam Matan
from collections import defaultdict

d1 = defaultdict(list)

for k, v in l:
    d1[k].append(v)

d = dict((k, Tuple(v)) for k, v in d1.iteritems())

d contient maintenant {1: ('A', 'B'), 2: ('C',)}

d1 Est un dict par défaut temporaire avec des listes en tant que valeurs, qui seront converties en tuples dans la dernière ligne. De cette façon, vous ajoutez des listes et ne recréez pas de tuples dans la boucle principale.

51
eumiro

Cette méthode est relativement efficace et assez compacte:

reduce(lambda x, (k,v): x[k].append(v) or x, l, defaultdict(list))

En Python3, cela devient (rendant les exportations explicites):

dict(functools.reduce(lambda x, d: x[d[0]].append(d[1]) or x, l, collections.defaultdict(list)))

Notez que la réduction a été déplacée vers functools et que les lambdas n'acceptent plus les tuples. Cette version fonctionne toujours en 2.6 et 2.7.

10
user2085084

Utilisation de listes au lieu de tuples comme valeurs dict:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
d={}
for key, val in l:
    d.setdefault(key, []).append(val)

print d
9
Sven Marnach

Les clés sont-elles déjà triées dans la liste de saisie? Si c'est le cas, vous avez une solution fonctionnelle:

import itertools

lst = [(1, 'A'), (1, 'B'), (2, 'C')]
dct = dict((key, Tuple(v for (k, v) in pairs)) 
           for (key, pairs) in itertools.groupby(lst, lambda pair: pair[0]))
print dct
# {1: ('A', 'B'), 2: ('C',)}
3
tokland