У Python, як мені прокрутити словник і змінити значення, якщо воно дорівнює чомусь?


76

Якщо значення None, я хотів би змінити його на "" (порожній рядок).

Я починаю так, але забуваю:

for k, v in mydict.items():
    if v is None:
... right?

Відповіді:


140
for k, v in mydict.iteritems():
    if v is None:
        mydict[k] = ''

У більш загальному випадку, наприклад, якщо ви додавали або видаляли ключі, може бути небезпечно змінити структуру контейнера, в якому ви циклюєтесь - тому використання itemsциклу в незалежному списку копії може бути розумним - але призначаючи інше значення при заданому існуючому індекси не НЕ несеш ніякої проблеми, тому, в Python 2.Any, це краще використовувати iteritems.

Однак у Python3 код видає AttributeError: 'dict' object has no attribute 'iteritems'помилку. Використовуйте items()замість iteritems()тут.

Зверніться до цієї публікації.


1
@ John, це стосується будь - якого вбудованого контейнера - так само, як до списку, так і до дикту - і я думаю, що "індекс" є більш загальним терміном, ніж "ключ".
Alex Martelli

2
mydict[k] = ''- ваш приклад оновлює kіндекс до незмінного об'єкта, - ''. Тож після цього kвказував би на зовсім інший об'єкт, ніж v. Чи не змінить це kіндекс певним чином, що може спричинити проблеми .iteritems()?
CivFan

4
@CivFan, nope, зміна або повторне присвоєння значення (на відміну від ключа ) не створює проблем з dict.iteritems.
Алекс Мартеллі,

Хм ... Мені цікаво, чи порада, яку слід використовувати .itemsдля циклу при додаванні / видаленні ключів, є розумною. Я не знаю деталей реалізації dict_itemsоб’єктів, але, схоже, у вас все ще можуть виникнути проблеми з ітерацією над ними в python3.x, якщо ви додаєте / видаляєте ключі. У такому випадку, мабуть, найбезпечніше переглядати список ключів: for k in list(mydict): v = mydict[k]; ...
mgilson

16

Ви можете створити розуміння дикту лише з елементів, значення яких відсутні, а потім оновити назад до оригіналу:

tmp = dict((k,"") for k,v in mydict.iteritems() if v is None)
mydict.update(tmp)

Оновлення - зробив кілька тестів продуктивності

Що ж, після спробування диктовок від 100 до 10000 предметів, із різним відсотком значень None, ефективність рішення Алекса є в цілому приблизно вдвічі швидшою, ніж це рішення.


Хм, для Python 2.7 я бачу приблизно однакову продуктивність (хоча метод Алекса все одно завжди швидший); Я пробував диктовки зі значеннями 1000 .. 100000 та відсутністю відсотків від 2 до 50 %%; для порівняння, метод від Buckley (з s / items / iteritems /) був приблизно в 4 рази повільнішим. Я думаю, це цікаво, оскільки ваша форма дозволяє змінити словник на ітерації.
ジ ョ ー ジ

9

Розуміння зазвичай швидше, і це має ту перевагу, що не редагує mydictпід час ітерації:

mydict = dict((k, v if v else '') for k, v in mydict.items())

Якщо ви використовуєте, .items()це не має значення (для python2), якщо ви зміните mydictсписок, що .items()повертається, не зміниться, навіть якщо ви додасте / видалите ключі відmydict
John La Rooy

4
Зміна лише значень у дикті ніколи не є проблемою; горе викликане додаванням / видаленням КЛЮЧІВ під час ітерації над dict. Розуміння швидше, ніж ЩО? Насправді швидко: копіювання цілого дикту, коли є один чи два Немає змін. Говорячи про Нонеса, вам слід було б if v is not Noneзамість if v(перечитати питання). Загальний підсумок: -1
Джон Мачин

Ваше рішення замінює 0, порожній список та все, що є помилковим у логічному контексті ''. Я б запропонував замінити if vна if v is None, це також більше відповідає PEP 8: python.org/dev/peps/pep-0008/#programming-reкомендації
статистичний декан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.