conversion de liste en Dictionnaire avec plusieurs valeurs par clé?
J'ai une liste Python qui contient des paires de clé / valeur:
l=[ [1, 'A'], [1, 'B'], [2, 'C'] ]
Je veux convertir la liste en un 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 pythonique plus élégante pour cette tâche?
4 réponses
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 defaultdict temporaire avec des listes comme 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.
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 reduce a été déplacé vers functools et que les lambdas n'acceptent plus les tuples. Cette version fonctionne toujours en 2.6 et 2.7.
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
Les clés sont-elles déjà triées dans la liste des entrées? 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',)}