Python визначає, як створити ключ або додати елемент до ключа?


161

У мене порожній словник. Ім'я: dict_x Це повинні мати ключі, значення яких є списками.

З окремої ітерації я отримую ключ (наприклад:) key_123та елемент (кортеж), який потрібно розмістити у списку значень dict_x's key_123.

Якщо цей ключ вже існує, я хочу додати цей елемент. Якщо цього ключа не існує, я хочу створити його з порожнім списком, а потім додати до нього або просто створити його з кортежем у ньому.

У майбутньому, коли цей ключ з’явиться знову, оскільки він існує, я хочу, щоб значення знову було додано.

Мій код складається з цього:

Отримайте ключ та значення.

Дивіться , якщо НЕ ключ існує в dict_x.

а якщо не створити: dict_x[key] == []

Після цього: dict_x[key].append(value)

Це спосіб це зробити? Чи варто спробувати використовувати try/exceptблоки?

Відповіді:


253

Використання dict.setdefault():

dic.setdefault(key,[]).append(value)

довідка (dict.setdefault) :

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

4
Я раніше це робив, dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]але ця відповідь говорить про набагато кращий шлях. Насправді це set()є аргументом і дозволяє використовувати add()метод ...
fatih_dur

66

Ось різні способи зробити це, щоб ви могли порівняти, як це виглядає, і вибрати те, що вам подобається. Я замовив їх таким чином, який, на мою думку, є найбільш "пітонічним" , і прокоментував плюси і мінуси, які можуть бути не очевидними на перший погляд:

Використання collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Плюси: Напевно, найкраща ефективність. Мінуси: недоступно в Python 2.4.x.

Використання dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Мінуси: Неефективне створення невикористаних list()s.

Використання try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

Або:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]

Привіт, чому ви вважаєте, чому .setdefault створює непотрібні словники?
Філ

2
Я не думаю, що .setdefault()створює зайві словники. Я думаю, що я створюю зайві lists (тобто []) у другому аргументі, .setdefault()який ніколи не використовується, якщо він keyвже існує. Я міг би використовувати dict.setdefault()(для переваги ефективного хешування ключів) і використовувати змінну для повторного використання невикористаних lists, але це додає ще кілька рядків коду.
антак

1
IIRC, в Python порожній список в рівності вважається константою на рівні байт-коду, але для цього потрібне певне підтвердження гуру байт-коду (або просто скористайтеся модулем катастрофи).
габоровий

Використання .setdefaultстворює регулярний спосіб, dictколи огляд відсутнього ключа призведе до деякого KeyErrorчасу, collections.defaultdict(list)створює, dictколи під час відсутності пошуку ключів буде вставлено порожнє list- я думаю, вам слід вибрати, залежно від того, яку поведінку ви хочете
Chris_Rands

Я спробував щось подібне до collection.defaultdict у власному коді, і це мало несподівані побічні ефекти. Наприклад, розгляньте такий обмін IDLE: >>> list_dict = засудження за замовчуванням (список) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Видається, що коли Python викликає значення за замовчуванням додає ключ до словника, не активно встановлюючи його, що створить безліч порожніх списків, якщо за замовчуванням використовується багато. Я збираюся виконувати власні функції обгортки для словника, неефективні, але, сподіваюся, більш передбачувані.
RDBury

26

Ви можете використовувати для цього вирок за замовчуванням .

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

Це дещо ефективніше, ніж setdefaultоскільки ви не закінчуєте створювати нові списки, які ви не закінчите використовувати. Кожен заклик до setdefaultзбирається створити новий список, навіть якщо елемент вже є у словнику.


14

Ви можете використовувати за замовчуванням в collections.

Приклад від doc:

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)

0
dictionary['key'] = dictionary.get('key', []) + list_to_append

1
Ви повинні пояснити (дуже незначну) перевагу, яку це має за наявності певних винятків; як просто код, не зрозуміло, для чого потрібна додаткова відповідь.
Девіс-оселедець

Привіт, просто альтернатива без додаткового імпорту. Це однозначно можна зробити за допомогою заяви if. Я просто пропоную альтернативу, використовуючи силу .get (), а не використовувати dict [].
Томаш Сільва Ебенспергер

У перших двох відповідях згадуються два різні способи без імпорту (хоча і ні dict.get).
Девіс-Оселедець
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.