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.
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 dict
s, 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
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.
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).
Personnellement, j'aime utiliser setdefault()
my_dict = {}
my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
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).
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
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.
Un peu en retard mais cela devrait fonctionner.
my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
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
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
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
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