Vérifiez si une clé donnée existe déjà dans un dictionnaire et incrémentez la

Étant donné un dictionnaire, Comment puis-je savoir si une clé donnée dans ce dictionnaire a déjà été définie sur une valeur non-None?

C'est-à-dire, je veux faire ceci:

my_dict = {}

if (my_dict[key] != None):
  my_dict[key] = 1
else:
  my_dict[key] += 1

C'est-à-dire, je veux incrémenter la valeur s'il y en a déjà une, ou la définir à 1 sinon.

235
demandé sur Niels Bom 2009-01-23 17:35:39

12 réponses

Vous recherchez collections.defaultdict (Disponible pour Python 2.5+). Ce

from collections import defaultdict

my_dict = defaultdict(int)
my_dict[key] += 1

Fera ce que vous voulez.

Régulière Python dicts, si il n'y a pas de valeur pour une clé donnée, vous pas get None lors de l'accès au dict -- a KeyError sera soulevée. Donc, si vous voulez utiliser un dict, au lieu de votre code, vous utilisez

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1
271
répondu dF. 2016-06-12 09:20:50

Je préfère le faire en une seule ligne de code.

my_dict = {}

my_dict[some_key] = my_dict.get(some_key, 0) + 1

Les dictionnaires ont une fonction, get, qui prend deux paramètres-la clé que vous voulez, et une valeur par défaut si elle n'existe pas. Je préfère cette méthode à defaultdict car vous voulez seulement gérer le cas où la clé n'existe pas dans cette ligne de code, pas partout.

227
répondu Andrew Wilkinson 2014-03-30 17:43:25

Vous avez besoin de l'idiome key in dict pour cela.

if key in my_dict and not (my_dict[key] is None):
  # do something
else:
  # do something else

Cependant, vous devriez probablement envisager d'utiliser defaultdict (comme suggéré par dF).

47
répondu Eli Bendersky 2009-01-23 15:38:55

Personnellement, j'aime utiliser setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
37
répondu kichik 2014-03-30 18:39:12

Pour répondre à la question " Comment puis-je savoir si un index donné dans ce dict a déjà été défini sur une valeur non-None", je préférerais ceci:

try:
  nonNone = my_dict[key] is not None
except KeyError:
  nonNone = False

Ceci est conforme au concept déjà invoqué D'EAFP (plus facile de demander pardon puis permission). Il évite également la recherche de clé en double dans le dictionnaire comme dans key in my_dict and my_dict[key] is not None ce qui est intéressant si la recherche est coûteuse.

Pour le problème réel {[6] } que vous avez posé, c'est-à-dire incrémenter un int s'il existe, ou en le définissant à une valeur par défaut sinon, je recommande également le

my_dict[key] = my_dict.get(key, default) + 1

Comme dans la réponse D'Andrew Wilkinson.

Il existe une troisième solution si vous stockez des objets modifiables dans votre dictionnaire. Un exemple courant pour cela est un multimap , où vous stockez une liste d'éléments pour vos clés. Dans ce cas, vous pouvez utiliser:

my_dict.setdefault(key, []).append(item)

Si une valeur pour key n'existe pas dans le dictionnaire, la méthode setdefault la définira sur le deuxième paramètre de setdefault. Il se comporte comme un my_dict[key] standard, renvoyant la valeur de la clé (qui peut être la nouvelle valeur définie).

14
répondu nd. 2010-02-04 10:32:38

Comme vous pouvez le voir à partir des nombreuses réponses, il existe plusieurs solutions. Une instance de LBYL (regardez avant de sauter) n'a pas encore été mentionnée, la méthode has_key ():

my_dict = {}

def add (key):
    if my_dict.has_key(key):
        my_dict[key] += 1
    else:
        my_dict[key] = 1

if __name__ == '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict
11
répondu bortzmeyer 2009-01-23 16:17:20

D'accord avec cgoldberg. Comment je le fais est:

try:
    dict[key] += 1
except KeyError:
    dict[key] = 1

Donc, faites-le comme ci-dessus, ou utilisez un dict par défaut comme d'autres l'ont suggéré. N'utilisez pas les instructions if. Ce n'est pas Pythonic.

10
répondu ryeguy 2009-01-23 15:09:59

Un peu en retard mais cela devrait fonctionner.

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
5
répondu Bob 2015-12-30 11:00:52

La façon dont vous essayez de le faire s'appelle LBYL (regardez avant de sauter), puisque vous vérifiez les conditions avant d'essayer d'incrémenter votre valeur.

L'autre approche est appelée EAFP (plus facile de demander pardon puis permission). Dans ce cas, vous essayez simplement l'opération (incrémenter la valeur). Si elle échoue, vous intercepter l'exception et définissez la valeur sur 1. C'est une façon un peu plus pythonique de le faire (OMI).

Http://mail.python.org/pipermail/python-list/2003-May/205182.html

5
répondu Corey Goldberg 2016-06-27 23:35:07

Cela ne répond pas directement à la question, mais pour moi, il semble que vous souhaitiez peut-être la fonctionnalité des collections .Compteur .

from collections import Counter

to_count = ["foo", "foo", "bar", "baz", "foo", "bar"]

count = Counter(to_count)

print(count)

print("acts just like the desired dictionary:")
print("bar occurs {} times".format(count["bar"]))

print("any item that does not occur in the list is set to 0:")
print("dog occurs {} times".format(count["dog"]))

print("can iterate over items from most frequent to least:")
for item, times in count.most_common():
    print("{} occurs {} times".format(item, times))

Il en résulte la sortie

Counter({'foo': 3, 'bar': 2, 'baz': 1})
acts just like the desired dictionary:
bar occurs 2 times
any item that does not occur in the list is set to 0:
dog occurs 0 times
can iterate over items from most frequent to least:
foo occurs 3 times
bar occurs 2 times
baz occurs 1 times
4
répondu Izaak van Dongen 2017-08-19 22:47:28

Voici un one-liner que j'ai trouvé récemment pour résoudre ce problème. Il est basé sur la méthode du dictionnaire setdefault :

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1
3
répondu Igor Gai 2012-12-10 14:12:56

Je le cherchais, Je ne l'ai pas trouvé sur le web puis j'ai tenté ma chance avec Try / Error et je l'ai trouvé

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1
1
répondu AbhishekKr 2014-03-30 17:46:24