Убедитесь, что данный ключ уже существует в словаре и увеличивает его

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

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

my_dict = {}

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

I.e., я хочу увеличить значение, если там уже есть, или установить его в противном случае.

Ответ 1

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

from collections import defaultdict

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

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

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

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

Ответ 2

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

my_dict = {}

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

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

Ответ 3

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

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

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

Ответ 4

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

my_dict = {}

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

Ответ 5

Чтобы ответить на вопрос "как я могу узнать, был ли заданный индекс в этом 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 [key], возвращая значение для ключа (которое может быть новым установленным значением).

Ответ 6

Согласовано cgoldberg. Как я это делаю:

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

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

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

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

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

Ответ 10

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

В результате получается вывод

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

Ответ 11

Вот один лайнер, который я недавно придумал для решения этой проблемы. Он основан на методе setdefault:

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

Ответ 12

Я искал его, не нашел его в Интернете, а затем попробовал удачу с Try/Error и нашел его

my_dict = {}

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