web-dev-qa-db-fra.com

Vérifier si une clé donnée existe déjà dans un dictionnaire et l'incrémenter

É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 autre que Aucune?

I.e., je veux faire ceci:

my_dict = {}

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

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

269
Ben

Vous recherchez collections.defaultdict (disponible pour Python 2.5+). Cette

_from collections import defaultdict

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

fera ce que vous voulez.

Pour Pythonnormal _ dicts, s'il n'y a pas de valeur pour une clé donnée, vous obtiendrez pas None lors de l’accès au dict - une KeyError sera levée. Donc, si vous voulez utiliser un dict normal, vous utiliserez plutôt

_if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1
_
307
dF.

Je préfère faire cela dans une ligne de code.

 mon_dict = {} 
 
 mon_dict [une_chonne] = mon_dict.get (une_couche, 0) + 1 

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

282
Andrew Wilkinson

Personnellement, j'aime bien utiliser setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
51
kichik

Pour cela, vous avez besoin du langage key in dict.

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).

48
Eli Bendersky

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

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

Cela est conforme au concept déjà invoqué d’EAFP (il est plus facile de demander pardon que l’autorisation). Cela évite également la recherche de clés 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 actuel que vous avez posé, c’est-à-dire incrémenter un int s'il existe ou lui attribuer une valeur par défaut, je recommande également la

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

comme dans la réponse de Andrew Wilkinson.

Il existe une troisième solution si vous stockez des objets modifiables dans votre dictionnaire. Un exemple courant pour cela est un carte multiple , dans lequel 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 la clé n'existe pas dans le dictionnaire, la méthode setdefault la définira sur le deuxième paramètre de setdefault. Il se comporte exactement comme un my_dict [clé] standard, renvoyant la valeur de la clé (qui peut être la valeur nouvellement définie).

18
nd.

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

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

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

13
ryeguy

Comme vous pouvez le constater parmi les 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 __== '__main__':
    add("foo")
    add("bar")
    add("foo")
    print my_dict
11
bortzmeyer

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 s'appelle EAFP (il est plus facile de demander pardon que d’autoriser). Dans ce cas, il vous suffirait d'essayer l'opération (incrémenter la valeur). En cas d'échec, vous interceptez l'exception et définissez la valeur sur 1. Il s'agit d'une manière légèrement plus pythonique de le faire (IMO).

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

7
Corey Goldberg

Cela ne répond pas directement à la question, mais pour moi, il semblerait que vous souhaitiez peut-être les fonctionnalités de collections.Counter .

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))

Cela se traduit par 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
5
Izaak van Dongen

Un peu tard mais ça devrait marcher.

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
5
Bob

Voici une ligne que j'ai récemment conçue pour résoudre ce problème. Elle est basée sur la méthode du dictionnaire setdefault :

my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1
3
Igor Gai

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
AbhishekKr