Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
665 views
in Technique[技术] by (71.8m points)

python 3.x - How can I replace a key:value pair by its value wherever the chosen key occurs in a deeply nested dictionary?

Other questions

This is a spin-off from How can I replace a key-value pair in a nested dictionary with the value from the same key-value pair? where the answer is working only in a one-time-nested dictionary. And it is a spin-off from Loop through all nested dictionary values? which I could not get to work on this problem.

Before:

I have a dictionary that is nested many times.

dict_nested = {
    "key_":{
        "key0a":{
            "key1a":{
                "sub_key2a":"sub_value2a",
                "sub_key2b":"sub_value2b"},
            "key1b":"value1b"},
        "key0b":{
            "key_XYZ":{
                "key1a":{
                    "sub_key2a":"sub_value2a",
                    "sub_key2b":"sub_value2b"},
                "key1b":"value1b"}
            }
        }
    }

After:

The result should look like this:

dict_nested_new = {
    "key_":{
        "key0a":{
            "sub_key2a":"sub_value2a",
            "sub_key2b":"sub_value2b",
            "key1b":"value1b"},
        "key0b":{
            "key_XYZ":{
                "sub_key2a":"sub_value2a",
                "sub_key2b":"sub_value2b",
                "key1b":"value1b"}
            }
        }
    }

Modifying a Python dict while iterating over it

When I looped through the items of the dictionary to delete / replace, I got the error

RuntimeError: dictionary changed size during iteration

which needs somehow to be avoided.

How can I replace the "key1a":SOME_VALUE key-value pair with its value each time it occurs somewhere in the dictionary?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As I understand it, you want to recursively search for a key in a nested dict and promote its value.

This might not be super efficient, but it should work. It also does not really explore dictionaries with lists as values but your example data does not have them so I did not implement that.

import copy
import json

def find_replace(this_dict, target_key):
    ## optional depending on if you care that you mutate this_dict
    this_dict = copy.deepcopy(this_dict)

    for key in this_dict:
        # if the current value is a dict, dive into it
        if isinstance(this_dict[key], dict):
            this_dict[key] = find_replace(this_dict[key], target_key)

        # if the current key is our target merge the values and remove the key
        if key == target_key:
            this_dict = {**this_dict, **this_dict[key]}
            del this_dict[key]

    return this_dict

dict_nested = {
    "key_":{
        "key0a":{
            "key1a":{
                "sub_key2a":"sub_value2a", 
                "sub_key2b":"sub_value2b"
            }, 
            "key1b":"value1b"
        },
        "key0b":{
            "key_XYZ":{
                "key1a":{
                    "sub_key2a":"sub_value2a", 
                    "sub_key2b":"sub_value2b",
                    "key1a": {
                        "sub_key3a":"sub_value3a", 
                        "sub_key3b":"sub_value3b"
                    }, 
                }, 
                "key1b":"value1b"
            }
        }
    }
}

dict_nested_new = find_replace(dict_nested, "key1a")
print(json.dumps(dict_nested_new, indent=4))

Should give you:

{
    "key_": {
        "key0a": {
            "key1b": "value1b",
            "sub_key2a": "sub_value2a",
            "sub_key2b": "sub_value2b"
        },
        "key0b": {
            "key_XYZ": {
                "key1b": "value1b",
                "sub_key2a": "sub_value2a",
                "sub_key2b": "sub_value2b",
                "sub_key3a": "sub_value3a",
                "sub_key3b": "sub_value3b"
            }
        }
    }
}

Note that I added an addition level of nesting with a sub-nested key match just to show that scenario. Additional optimizations like support for lists and avoiding updates to unchanged keys available for a reasonable fee :-P


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...