Search code examples
pythondictionaryrename

Iterate over nested dictionary and replacing the keys in Python


I'm trying to replace all spaces in the dictionary's keys with "_" the code is:

test_parameters = {
        'Debug Properties': {'DUT WRT Dump': True, 'DUT WRT Tool': True, "DUT Preset": "Stater"},
        'Attenuation Values': {'DUT To BTOE': '3'},
        'BT Parameters': {'Connection Interval': '7.5', 'Traffic_Duration': '30'},
    }

for group in test_parameters:
    new_group_name = group.replace(" ", "_")
    group_value = test_parameters.pop(group)
    test_parameters.update({new_group_name: group_value})
    for key in test_parameters[new_group_name]:
        new_key_name = key.replace(" ", "_")
        key_value = test_parameters[new_group_name].pop(key)
        test_parameters[new_group_name].update({new_key_name: key_value})

the first nested dictionary 'Debug Properties' working fine, then when the code finish the last code line for 'DUT To BTOE' the for is failing with error "RuntimeError: dictionary keys changed during iteration"

how can I achieve this functionality?

Thanks


Solution

  • One way is to create a new dictionary with the desired keys.

    To be more flexible with the depth level, do it with a recursive approach:

    from pprint import pprint
    from typing import Any
    
    test_parameters = {
        "Debug Properties": {
            "DUT WRT Dump": True,
            "DUT WRT Tool": True,
            "DUT Preset": "Stater",
        },
        "Attenuation Values": {"DUT To BTOE": "3"},
        "BT Parameters": {"Connection Interval": "7.5", "Traffic_Duration": "30"},
    }
    
    def replace_nested(d: dict[str, Any]):
        return {
            k.replace(" ", "_"): replace_nested(v) if isinstance(v, dict) else v
            for k, v in d.items()
        }
    
    pprint(replace_nested(test_parameters), sort_dicts=False)
    

    output:

    {'Debug_Properties': {'DUT_WRT_Dump': True,
                          'DUT_WRT_Tool': True,
                          'DUT_Preset': 'Stater'},
     'Attenuation_Values': {'DUT_To_BTOE': '3'},
     'BT_Parameters': {'Connection_Interval': '7.5', 'Traffic_Duration': '30'}}