web-dev-qa-db-fra.com

Python créant un dictionnaire de listes

Je veux créer un dictionnaire dont les valeurs sont des listes. Par exemple:

{
  1: ['1'],
  2: ['1','2'],
  3: ['2']
}

Si je fais:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d[j].append(i)

Je reçois un KeyError, parce que d [...] n'est pas une liste. Dans ce cas, je peux ajouter le code suivant après l’affectation d’un pour initialiser le dictionnaire.

for x in range(1, 4):
    d[x] = list()

Y a-t-il une meilleure manière de faire cela? Disons que je ne connais pas les clés dont j’aurai besoin jusqu’à ce que je sois dans la deuxième boucle for. Par exemple:

class relation:
    scope_list = list()
...
d = dict()
for relation in relation_list:
    for scope_item in relation.scope_list:
        d[scope_item].append(relation)

Une alternative serait alors remplacer

d[scope_item].append(relation)

avec

if d.has_key(scope_item):
    d[scope_item].append(relation)
else:
    d[scope_item] = [relation,]

Quelle est la meilleure façon de gérer cela? Idéalement, ajouter ne ferait que "fonctionner". Y a-t-il un moyen d'exprimer que je veuille un dictionnaire de listes vides, même si je ne connais pas toutes les clés lorsque je crée la liste pour la première fois?

204
user118662

Vous pouvez utiliser defaultdict :

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = ['1', '2']
>>> for i in a:
...   for j in range(int(i), int(i) + 2):
...     d[j].append(i)
...
>>> d
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']})
>>> d.items()
[(1, ['1']), (2, ['1', '2']), (3, ['2'])]
266
bernie

Vous pouvez le construire avec une compréhension de liste comme ceci:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2'])
{'1': [1, 2], '2': [2, 3]}

Et pour la deuxième partie de votre question, utilisez defaultdict

>>> from collections import defaultdict
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
        d[k].append(v)

>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
49
Nadia Alramli

Utilisez setdefault:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d.setdefault(j, []).append(i)

print d  # prints {1: ['1'], 2: ['1', '2'], 3: ['2']}

La fonction setdefault au nom plutôt étrange dit "Obtenez la valeur avec cette clé, ou si cette clé n'y est pas, ajoutez cette valeur, puis renvoyez-la".

Edit: Comme d'autres l'ont souligné à juste titre, defaultdict est un choix meilleur et plus moderne. setdefault est toujours utile dans les anciennes versions de Python (avant la version 2.5).

29
RichieHindle

Vous avez déjà répondu à votre question, mais vous pouvez remplacer les lignes suivantes:

if d.has_key(scope_item):

avec:

if scope_item in d:

C'est-à-dire que d fait référence à d.keys() dans cette construction. Parfois, defaultdict n'est pas la meilleure option (par exemple, si vous souhaitez exécuter plusieurs lignes de code après le else associé au précédent if), et que je trouve le in syntaxe plus facile à lire.

2
spiffyman

Personnellement, je viens d'utiliser JSON pour convertir des choses en chaînes et en retour. Les cordes je comprends.

import json
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
mydict = {}
hash = json.dumps(s)
mydict[hash] = "whatever"
print mydict
#{'[["yellow", 1], ["blue", 2], ["yellow", 3], ["blue", 4], ["red", 1]]': 'whatever'}
1
john ktejik

moyen facile est:

a = [1,2]
d = {}
for i in a:
  d[i]=[i, ]

print(d)
{'1': [1, ], '2':[2, ]}
1
Henning Lee