Розуміння словника Python


386

Чи можливо створити розуміння словника в Python (для клавіш)?

Без розуміння списку ви можете використовувати щось подібне:

l = []
for n in range(1, 11):
    l.append(n)

Ми можемо скоротити це до списку розуміння: l = [n for n in range(1, 11)].

Однак скажіть, що я хочу встановити ключі словника на однакове значення. Я можу зробити:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

Я спробував це:

d = {}
d[i for i in range(1, 11)] = True

Однак я отримую SyntaxErrorна for.

Окрім цього (мені ця частина не потрібна, а просто цікаво), чи можете ви встановити ключі словника до набору різних значень, як це:

d = {}
for n in range(1, 11):
    d[n] = n

Чи можливо це за допомогою розуміння словника?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Це також піднімає SyntaxErrorна for.


3
Для інформації майбутніх читачів: масиви NumPy дозволяють встановлювати кілька елементів на одне значення або список значень, як ви намагаєтеся зробити. Хоча якщо у вас ще немає причин використовувати NumPy, це, мабуть, не варто лише для цієї функції.
David Z

Відповіді:


520

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

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Якщо ви хочете встановити їх усі на "True":

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

Те, що вам здається, просите, це спосіб встановити кілька клавіш одразу на існуючому словнику. Для цього немає прямого ярлика. Ви можете або зробити цикл, як ви вже показали, або ви можете використовувати розуміння словника, щоб створити новий дикт із новими значеннями, а потім зробити, oldDict.update(newDict)щоб об'єднати нові значення у старий.


15
FWIW, dict.updateтакож може приймати ітерабельну пару ключових значень, як і dictконструктор
mgilson

6
Зауважте, що якщо ви створили словник з усіма однаковими значеннями, використовуйте dict.fromkeys(). Тому для встановлення всіх значень Trueвикористовуйте dict.fromkeys(range(5), True). Слідкуйте, значення не копіюється , тому ви можете уникнути цього, коли у вас є змінне значення; її поділять між усіма ключами.
Martijn Pieters

2
Примітка: клавіші можуть бути результатом методу , а також: { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2}. Як можна зробити в одному вираженні: { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 }.
Зааєр

151

Ви можете використовувати dict.fromkeysметод класу ...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

Це найшвидший спосіб створити словник, де всі клавіші відображають однакове значення.

Але нічого НЕ використовувати це із змінними об'єктами :

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

Якщо вам не потрібно ініціалізувати всі ключі, також defaultdictможе бути корисним:

from collections import defaultdict
d = defaultdict(True)

Щоб відповісти на другу частину, розуміння дикту - це саме те, що вам потрібно:

{k: k for k in range(10)}

Ви, мабуть, не повинні цього робити, але ви також можете створити підклас, dictякий працює дещо як a, defaultdictякщо ви перекриєте __missing__:

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}

Зауважте, що у випадку з d = defaultdict(lambda: True)лямбда не потрібно, оскільки True є (або не повинно) бути змінним.
rhbvkleef

28
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}

22

Мені дуже подобається коментар @mgilson, оскільки якщо у вас є два ітерабелі, один, який відповідає клавішам, а інший значенням, ви також можете зробити наступне.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

давання

d = {'a': 1, 'b': 2, 'c': 3}


4
Використання розуміння Dict:{i:j for i in keys for j in values}
LoMaPh

11

Використовуйте dict () у списку кортежів, це рішення дозволить мати довільні значення у кожному списку, якщо вони однакової довжини

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])

12
Як зауваження, це те саме, щоd = dict(zip(i_s,x_s))
mgilson

10

Розглянемо цей приклад підрахунку зустрічальності слів у списку з використанням розуміння словника

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

І результат є

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}

Це цікаво, хоча і не найефективніше, оскільки ви кілька разів будете рахувати ключі на зразок "привіт"
FuriousGeorge

7

Основна мета розуміння списку - створити новий список на основі іншого, не змінюючи або знищуючи початковий список.

Замість того, щоб писати

    l = []
    for n in range(1, 11):
        l.append(n)

або

    l = [n for n in range(1, 11)]

ви повинні писати тільки

    l = range(1, 11)

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

Щоб отримати новий словник з усіма ключами, встановленими на одне значення, на основі іншого диктату, зробіть це:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Ви отримуєте SyntaxError тому, що коли пишете

    d = {}
    d[i for i in range(1, 11)] = True

ви в основному говорите: "Встановити мій ключ" i для i в діапазоні (1, 11) "на" Істинно "і" i для i в діапазоні (1, 11) "- не допустимий ключ, це лише помилка синтаксису. Якби дикти підтримували списки як ключі, ви зробили б щось подібне

    d[[i for i in range(1, 11)]] = True

і ні

    d[i for i in range(1, 11)] = True

але списки не є доступними для доступу, тому ви не можете використовувати їх як клавіші dict.


-3

ви не можете хеш-лист такого. спробуйте це замість цього, тут використовуються кортежі

d[tuple([i for i in range(1,11)])] = True
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.