Проверьте, существует ли данный ключ в словаре, и увеличьте его
По заданному словарю, как я могу узнать, задан ли для данного ключа в этом словаре ненулевое значение?
Т.е. я хочу сделать это:
my_dict = {}
if (my_dict[key] != None):
my_dict[key] = 1
else:
my_dict[key] += 1
Т.е. я хочу увеличить значение, если оно уже есть, или установить его равным 1, в противном случае.
12 ответов
Ты ищешь collections.defaultdict
(доступно для Python 2.5+). это
from collections import defaultdict
my_dict = defaultdict(int)
my_dict[key] += 1
будет делать то, что вы хотите.
Для обычного Python dict
s, если для данного ключа нет значения, вы не получите None
при доступе к диктату - KeyError
будет поднят. Так что если вы хотите использовать обычный dict
вместо вашего кода вы бы использовали
if key in my_dict:
my_dict[key] += 1
else:
my_dict[key] = 1
Я предпочитаю делать это в одной строке кода.
my_dict = {} my_dict [some_key] = my_dict.get (some_key, 0) + 1
В словарях есть функция get, которая принимает два параметра - нужный вам ключ и значение по умолчанию, если оно не существует. Я предпочитаю этот метод defaultdict, так как вы хотите обрабатывать только тот случай, когда ключ не существует в этой строке кода, а не везде.
Мне лично нравится использовать setdefault()
my_dict = {}
my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
Вам нужно key in dict
идиома для этого.
if key in my_dict and not (my_dict[key] is None):
# do something
else:
# do something else
Тем не менее, вы, вероятно, должны рассмотреть возможность использования defaultdict
(как предложил Д.Ф.)
Чтобы ответить на вопрос "как я могу узнать, был ли заданный индекс в этом dict уже не равным None", я бы предпочел следующее:
try:
nonNone = my_dict[key] is not None
except KeyError:
nonNone = False
Это соответствует уже задействованной концепции EAFP (проще просить прощения, чем разрешения). Это также позволяет избежать поиска дубликатов ключей в словаре, как это было бы в key in my_dict and my_dict[key] is not None
что интересно, если поиск дорогой.
Для реальной проблемы, которую вы поставили, то есть для увеличения значения int, если оно существует, или установки значения по умолчанию в противном случае, я также рекомендую
my_dict[key] = my_dict.get(key, default) + 1
как в ответе Эндрю Уилкинсона.
Существует третье решение, если вы храните изменяемые объекты в вашем словаре. Типичным примером этого является мультикарта, где вы храните список элементов для ваших ключей. В этом случае вы можете использовать:
my_dict.setdefault(key, []).append(item)
Если значение для ключа не существует в словаре, метод setdefault установит для него второй параметр setdefault. Он ведет себя так же, как стандартный my_dict[ключ], возвращая значение для ключа (которое может быть вновь установленным значением).
Договорились с cgoldberg. Как я это делаю
try:
dict[key] += 1
except KeyError:
dict[key] = 1
Так что либо делайте это, как указано выше, либо используйте dict по умолчанию, как предлагали другие. Не используйте операторы if. Это не Pythonic.
Как видно из множества ответов, есть несколько решений. Один экземпляр LBYL (посмотрите, прежде чем прыгнуть) еще не был упомянут, метод 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
То, как вы пытаетесь это сделать, называется LBYL (посмотрите, прежде чем прыгнуть), так как вы проверяете условия, прежде чем пытаться увеличить свое значение.
Другой подход называется EAFP (проще просить прощения, чем разрешения). В этом случае вы просто попытаетесь выполнить операцию (увеличить значение). Если это не удается, вы перехватываете исключение и устанавливаете значение 1. Это немного более Pythonic способ сделать это (IMO).
http://mail.python.org/pipermail/python-list/2003-May/205182.html
Немного поздно, но это должно сработать.
my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
Это не прямой ответ на вопрос, но для меня это выглядит так, как будто вам может понадобиться функциональность коллекций. Счетчик.
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))
Это приводит к выводу
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
Вот одна строка, которую я недавно придумал для решения этой проблемы. Он основан на методе словаря setdefault:
my_dict = {}
my_dict[key] = my_dict.setdefault(key, 0) + 1
Я искал его, не нашел его в сети, затем попытал счастья с помощью Try/Error и нашел его
my_dict = {}
if my_dict.__contains__(some_key):
my_dict[some_key] += 1
else:
my_dict[some_key] = 1