There is a multi-level dictionary in which you need to change the point to the underscore(for importing into MongoDB) in certain keys(second-level keys and the keys of the'url_dict'dictionary).

I, in order not to receive the errors of"dictionary changed size during iteration", create a copy of the dictionary(even .copy added for greater fidelity) to go through all the necessary keys, and delete it in the main dictionary.The problem is that even if I work with a copy of a copy and do not change it in any way(I only change the original source), Python still believes that I am reducing the size of the dictionary.

Code:

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]


I sit, eye twitches.I would be grateful for any advice :)
  • Error climbs when it comes to the second iteration:

    for dict_key in ad_items_dict_copy [item] [in_key] ['url_dict']:


    That is, he decided. that I deleted something from the url_dict dictionary. But I didn’t delete anything, I deleted it from a completely different dictionary, which shouldn’t affect my double copy in any way. Or something I do not understand?
    – Curious74 Aug 17 '17 at 18:53
  • Manic Office: The implementation is useful, and most likely I will, thank you very much :) But, it’s still not at all clear why an error occurs in my implementation. Moreover, if I want to replace not all the dots, but only a certain level, or just a specific dictionary, then the solution is already a bit wrong. – Curious74 Aug 17 '17 at 18:55
  • Maybe you need a deepcopy – Perverted71 Aug 17 '17 at 18:58
  • Curious74: you can always remove recursion for"only a certain level or a specific dictionary", and if so you will do the code under python2 in the answer marked with the answer – Manic Office Aug 17 '17 at 19:19

1 Answers 1

ad_items_dict_copy=ad_items_dict.copy()
you will only have this superficial copy of dictionaries!
nested dictionaries from which you delete keys during iteration will be the same in both cases.

if you need direct copy you can use deepcopy

but in general you can use similar(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}}}}

no copying is required at all, and the code is cleaner.
  • Understood, thank you very much, did not know :) – Curious74 Aug 17 '17 at 19:20
  • And what, it is possible just like that through replace to change the keys of the dictionary? :) – Curious74 Aug 17 '17 at 19:21
  • I mean:

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


    Or is it technically considered that we are changing not the keys of the dictionary, but the replacement as we do in string?
    – Curious74 Aug 17 '17 at 19:22
  • [[sortarage]]: the whole point is that we do not change the dictionary, we create a new one, but we create it immediately with the keys we need! The original dictionaries remain as they were, only links to old versions of dictionaries are replaced by new ones. – Planet of Aug 17 '17 at 19:26
  • Planet of: Understood, thanks again :) – Curious74 Aug 17 '17 at 19:31