Verificar se uma determinada chave já existir em um dicionário e incrementá-lo
-
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.
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 dict
s 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