Verificar se uma determinada chave já existir em um dicionário e incrementá-lo

StackOverflow https://stackoverflow.com/questions/473099

  •  19-08-2019
  •  | 
  •  

Pergunta

Dado um dicionário, como posso descobrir se uma determinada chave em que dicionário já foi definido para um valor diferente de Nenhum?

.

ou seja, eu quero fazer isso:

my_dict = {}

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

i., Quero incrementar o valor se já existe um lá, ou configurá-lo para 1 caso contrário.

Foi útil?

Solução

Você está procurando collections.defaultdict (disponível para Python 2.5 +). Este

from collections import defaultdict

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

vai fazer o que quiser.

Para dicts regulares Python, se não houver nenhum valor para uma determinada chave, você irá não obter None ao acessar o dict - um KeyError será gerado. Então, se você quiser usar um dict regular, em vez de seu código que você usaria

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1

Outras dicas

Eu prefiro fazer isso em uma linha de código.

my_dict = {}

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

Os dicionários têm uma função, obter, que tem dois parâmetros - a chave que você deseja, e um valor padrão se ele não existir. Eu prefiro este método para defaultdict como você só quer lidar com o caso em que a chave não existir nesta linha um de código, não em todos os lugares.

Eu, pessoalmente, como o uso de setdefault()

my_dict = {}

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

Você precisa do idioma key in dict para isso.

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

No entanto, você provavelmente deve considerar o uso de defaultdict (como dF sugerido).

Para responder à pergunta " como posso descobrir se um determinado índice em que dict já foi definido para um valor diferente de Nenhum ", eu preferiria esta:

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

Este está em conformidade com o conceito já invocado de EAFP (mais fácil pedir perdão em seguida, permissão). Ele também evita a pesquisa de chave duplicada no dicionário como seria na key in my_dict and my_dict[key] is not None o que é interessante se lookup é caro.

Para o real problema que você tenha que se colocam, ou seja, incrementar um int se existe, ou defini-lo como um valor padrão de outra forma, eu também recomendo o

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

como na resposta de Andrew Wilkinson.

Há uma terceira solução, se você estiver armazenando objetos modifyable em seu dicionário. Um exemplo comum para isso é uma multimap , onde você armazenar uma lista de elementos para suas chaves. Nesse caso, você pode usar:

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

Se um valor para chave não existir no dicionário, o método setdefault irá configurá-lo para o segundo parâmetro de setdefault. Ele se comporta exatamente como um my_dict padrão [key], devolvendo o valor para a chave (que pode ser o novo valor definido).

Concordou com cgoldberg. Como eu faço é:

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

Assim, ou fazê-lo como acima, ou usar um dicionário padrão como já foi sugerido. Não use se declarações. Isso não é Pythonic.

Como você pode ver pelas muitas respostas, existem várias soluções. Uma instância de LBYL (olhar antes de saltar) ainda não foi mencionado, o método 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

A maneira que você está tentando fazer é chamado LBYL (olhar antes de salto), uma vez que está a verificar as condições antes de tentar aumentar o seu valor.

A outra abordagem é chamada EAFP (mais fácil pedir perdão em seguida, permissão). Nesse caso, você teria apenas tente a operação (incrementar o valor). Se ele falhar, você capturar a exceção e defina o valor para 1. Esta é uma maneira um pouco mais Pythonic para fazê-lo (IMO).

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

Um pouco tarde, mas isso deve funcionar.

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

Isto não está a responder diretamente à pergunta, mas para mim, parece que você pode querer a funcionalidade do 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))

Isso resulta na saída

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

Aqui está um forro que eu vim com recentemente para resolver este problema. É baseado na href="http://docs.python.org/2/library/stdtypes.html#dict.setdefault" rel="nofollow"> setdefault método de dicionário :

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

Eu estava procurando por isso, não os encontrou em web, em seguida, tentou a sorte com Try / erro e achei

my_dict = {}

if my_dict.__contains__(some_key):
  my_dict[some_key] += 1
else:
  my_dict[some_key] = 1
scroll top