sortarage
@sortarage
Я тучка-тучка-тучка, я вовсе не медведь

Как сделать замену ключей в словаре без «dictionary changed size during iteration»?

Есть многоуровневый словарь, в котором нужно в определенных ключах (ключах второго уровня, и ключах словаря 'url_dict') поменять точку на нижнее подчеркивание (для импорта в MongoDB).

Я, чтобы не получать ошибки "dictionary changed size during iteration", создаю копию словаря (даже .copy добавил для пущей верности), чтобы пройтись по всем нужным ключам, а в основном словаре - удалить. Проблема в том, что даже если я работаю с копией копии и никак ее не изменяю (изменяю только первоисточник), Питон все равно считает, что я уменьшаю размер словаря.

Код:

ad_items_dict_copy = ad_items_dict.copy()

for item in ad_items_dict_copy:
    for in_key in ad_items_dict_copy[item]:
        
        for dict_key in ad_items_dict_copy[item][in_key]['url_dict']:
            new_dict_key = dict_key.replace('.','_')
            ad_items_dict[item][in_key]['url_dict'][new_dict_key] = ad_items_dict[item][in_key]['url_dict'][dict_key]
            del ad_items_dict[item][in_key]['url_dict'][dict_key]
            
        new_in_key = in_key.replace('.','_')
        ad_items_dict[item][new_in_key] = ad_items_dict[item][in_key]
        del ad_items_dict[item][in_key]


Сижу, глаз дергается. Буду благодарен за любой совет :)
  • Вопрос задан
  • 495 просмотров
Решения вопроса 1
ad_items_dict_copy = ad_items_dict.copy()
это у вас сделает только поверхностную копию словарей!
вложенные словари из которых вы удаляете ключи при итерации в обоих случаях будут одинаковым.

если вам нужно прям скопировать можно воспользоваться deepcopy

а вообще можно воспользоваться подобным (py3):
ad_items_dict = {'1': {
    '1.1': {
        'url_dict': {
            '1.1': 123
        }
    }
}}


for kitem, vitem in ad_items_dict.items():
    for value in vitem.values():
        value['url_dict'] = {k.replace('.', '_'): v for k, v in value['url_dict'].items()}

    ad_items_dict[kitem] = {k.replace('.', '_'): v for k, v in vitem.items()}

# {'1': {'1_1': {'url_dict': {'1_1': 123}}}}

никаких копирований не требуется вообще, и код чище.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы