Проверьте, существует ли данный ключ в словаре, и увеличьте его - PullRequest
260 голосов
/ 23 января 2009

Учитывая словарь, как я могу узнать, было ли заданному ключу в этом словаре значение не None?

Т.е., я хочу сделать это:

my_dict = {}

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

Т.е., я хочу увеличить значение, если оно уже есть, или установить его равным 1.

Ответы [ 12 ]

299 голосов
/ 23 января 2009

Вы ищете collections.defaultdict (доступно для Python 2.5+). Это

from collections import defaultdict

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

будет делать то, что вы хотите.

Для обычных Python dict s, если для данного ключа нет значения, вы не получите None при доступе к dict - будет поднят KeyError. Поэтому, если вы хотите использовать обычный dict, вместо вашего кода вы должны использовать

if key in my_dict:
    my_dict[key] += 1
else:
    my_dict[key] = 1
269 голосов
/ 23 января 2009

Я предпочитаю делать это в одной строке кода.

my_dict = {}

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

В словарях есть функция get, которая принимает два параметра - нужный вам ключ и значение по умолчанию, если оно не существует. Я предпочитаю, чтобы этот метод использовался по умолчанию, поскольку вы хотите обрабатывать только тот случай, когда ключ не существует в этой строке кода, а не везде.

49 голосов
/ 28 октября 2011

Мне лично нравится использовать setdefault()

my_dict = {}

my_dict.setdefault(some_key, 0)
my_dict[some_key] += 1
48 голосов
/ 23 января 2009

Для этого вам нужна идиома key in dict.

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

Тем не менее, вам, вероятно, следует рассмотреть возможность использования defaultdict (как указано в dF).

18 голосов
/ 04 февраля 2010

Чтобы ответить на вопрос ", как я могу узнать, было ли заданному индексу в этом 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

как в ответе Эндрю Уилкинсона.

Существует третье решение, если вы храните изменяемые объекты в своем словаре. Типичным примером этого является multimap , где вы храните список элементов для ваших ключей. В этом случае вы можете использовать:

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

Если значение для ключа не существует в словаре, метод setdefault установит для него второй параметр setdefault. Он ведет себя так же, как стандартный my_dict [ключ], возвращая значение для ключа (которое может быть вновь установленным значением).

13 голосов
/ 23 января 2009

Договорились с cgoldberg. Как мне это сделать:

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

Так что либо делайте это, как указано выше, либо используйте dict по умолчанию, как предлагали другие. Не используйте операторы if. Это не Pythonic.

11 голосов
/ 23 января 2009

Как видно из множества ответов, есть несколько решений. Один экземпляр 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
7 голосов
/ 23 января 2009

Способ, которым вы пытаетесь это сделать, называется LBYL (посмотрите, прежде чем вы прыгнете), поскольку вы проверяете условия перед тем, как пытаться увеличить свое значение.

Другой подход называется EAFP (проще просить прощения, чем разрешения). В этом случае вы просто попытаетесь выполнить операцию (увеличить значение). Если это не удается, вы перехватываете исключение и устанавливаете значение 1. Это немного более Pythonic способ сделать это (IMO).

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

5 голосов
/ 20 августа 2017

Это прямо не отвечает на вопрос, но мне кажется, что вам может понадобиться функциональность collection.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))

Это приводит к выводу

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 голосов
/ 30 декабря 2015

Немного поздно, но это должно сработать.

my_dict = {}
my_dict[key] = my_dict[key] + 1 if key in my_dict else 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...