web-dev-qa-db-fra.com

Python Compréhension du dictionnaire

Est-il possible de créer une compréhension du dictionnaire dans Python (pour les clés)?

Sans compréhension de la liste, vous pouvez utiliser quelque chose comme ceci:

l = []
for n in range(1, 11):
    l.append(n)

Nous pouvons raccourcir ceci en une compréhension de liste: l = [n for n in range(1, 11)].

Cependant, disons que je veux définir les clés d'un dictionnaire sur la même valeur. Je peux faire:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

J'ai essayé ceci:

d = {}
d[i for i in range(1, 11)] = True

Cependant, j'ai un SyntaxError sur le for.

En plus (je n'ai pas besoin de cette partie, mais je me demandais), pouvez-vous définir les clés d'un dictionnaire pour un tas de valeurs différentes, comme ceci:

d = {}
for n in range(1, 11):
    d[n] = n

Est-ce possible avec une compréhension du dictionnaire?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Cela soulève également un SyntaxError sur le for.

356
Rushy Panchal

Il y a compréhension du dictionnaire dans Python 2.7 + , mais ils ne fonctionnent pas exactement de la façon que vous essayez. Comme une liste de compréhension, ils créent un nouveau dictionnaire ; vous ne pouvez pas les utiliser pour ajouter des clés à un dictionnaire existant. En outre, vous devez spécifier les clés et les valeurs, bien que vous puissiez bien sûr spécifier une valeur factice si vous le souhaitez.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Si vous souhaitez les définir tous sur True:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

Ce que vous semblez demander, c'est un moyen de définir plusieurs clés à la fois sur un dictionnaire existant. Il n'y a pas de raccourci direct pour cela. Vous pouvez soit boucler comme vous l’avez déjà montré, soit utiliser un dictionnaire pour créer un nouveau dict avec les nouvelles valeurs, puis faire oldDict.update(newDict) pour fusionner les nouvelles valeurs dans l’ancien dict.

481
BrenBarn

Vous pouvez utiliser la méthode dict.fromkeys ...

_>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}
_

C'est le moyen le plus rapide de créer un dictionnaire où toutes les clés correspondent à la même valeur.

Mais do pas utilise ceci avec des objets mutables :

_d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!
_

Si vous n'avez pas réellement besoin de pour initialiser toutes les clés, un defaultdict pourrait également être utile:

_from collections import defaultdict
d = defaultdict(True)
_

Pour répondre à la deuxième partie, une dictée est exactement ce dont vous avez besoin:

_{k: k for k in range(10)}
_

Vous ne devriez probablement pas faire cela, mais vous pouvez également créer une sous-classe de dict qui fonctionne un peu comme un defaultdict si vous remplacez ___missing___:

_>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}
_
146
mgilson
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}
27
NPE

J'aime beaucoup le commentaire @mgilson, car si vous avez deux itérables, l'un qui correspond aux clés et l'autre aux valeurs, vous pouvez également procéder comme suit.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(Zip(keys, values))

donnant

d = {'a': 1, 'b': 2, 'c': 3}

20
ehontz

Utilisez dict () sur une liste de tuples, cette solution vous permettra d’avoir des valeurs arbitraires dans chaque liste, à condition qu’elles aient la même longueur.

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])
11
Bryan

Considérez cet exemple de comptage de l'occurrence de mots dans une liste à l'aide de la compréhension du dictionnaire

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

Et le résultat est

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}
10
adonese

Le but principal d'une compréhension de liste est de créer une nouvelle liste basée sur une autre liste sans changer ni détruire la liste d'origine.

Au lieu d'écrire

    l = []
    for n in range(1, 11):
        l.append(n)

ou

    l = [n for n in range(1, 11)]

vous devriez écrire seulement

    l = range(1, 11)

Dans les deux blocs de code supérieurs, vous créez une nouvelle liste, parcourez-la et renvoyez simplement chaque élément. C'est juste un moyen coûteux de créer une copie de liste.

Pour obtenir un nouveau dictionnaire avec toutes les clés définies sur la même valeur en fonction d'un autre dict, procédez comme suit:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Vous recevez une SyntaxError car lorsque vous écrivez

    d = {}
    d[i for i in range(1, 11)] = True

vous dites essentiellement: "Régler ma clé 'i pour i dans la plage (1, 11)' sur True" et "i pour i dans la plage (1, 11)" n'est pas une clé valide, c'est juste une erreur de syntaxe. Si les cartes supportaient les listes en tant que clés, vous feriez quelque chose comme:

    d[[i for i in range(1, 11)]] = True

et pas

    d[i for i in range(1, 11)] = True

mais les listes ne sont pas hashable, vous ne pouvez donc pas les utiliser comme clés dict.

7
Bonifacio2