我怎样才能删除一个 key:value 对,只要选择的键出现在深层嵌套的字典中?

How can I remove a key:value pair wherever the chosen key occurs in a deeply nested dictionary?

关于

这个问题是关于在找到的键上删除 key:value 对,遍历整个字典的最基本问题。

其他问题


之前:

我有一个嵌套了很多次的字典。

{
    "key0": {
        "key1a": {
            "sub_key2a": "sub_value2a",
            "sub_key2b": "sub_value2b"
        },
        "key1b": {
            "key_XYZ": {
                "sub_key2a": "sub_value2a",
                "sub_key2b": "sub_value2b"
            }
        }
    }
}

之后:

结果应如下所示,删除所有 "sub_key2a" 个键及其值:

{
    "key0": {
        "key1a": {
            "sub_key2b": "sub_value2b"
        },
        "key1b": {
            "key_XYZ": {
                "sub_key2b": "sub_value2b"
            }
        }
    }
}

在迭代时修改 Python 字典

当我遍历要删除的字典项时,出现错误

RuntimeError: dictionary changed size during iteration

这需要以某种方式避免。

每次字典中某处出现键 "sub_key2a" 时,如何删除 "sub_key2a": SOME_VALUE 键值对?

技巧

诀窍是提前找出一个target_key是否在下一个children (= this_dict[key] =当前 dict 迭代的)before 你递归地达到 child 级别。只有这样,您仍然可以在遍历字典时删除 child 级别的 key:value 对。一旦您达到与要删除的密钥相同的级别,然后尝试从那里删除它,您会收到错误消息:

RuntimeError: dictionary changed size during iteration

代码

因此,代码如下所示:

import copy

def find_remove(this_dict, target_key, bln_overwrite_dict=False):
    if not bln_overwrite_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):
            if target_key in this_dict[key]:
                this_dict[key].pop(target_key)

            this_dict[key] = find_remove(this_dict[key], target_key)

    return this_dict

dict_nested_new = find_remove(nested_dict, "sub_key2a")

学分

这是 几乎 spin-off 的副本。但是我花了一些时间来更改该答案,以便它可以通过其键删除 key:value 。这就是我分享这个的原因,请注意 95% 的功劳归于 link!

“spun-off 答案”的主要附加值是您在进入下一个递归之前在 中搜索 target_key通过检查 if target_key in this_dict[key]:.

级别

旁注:格式化输出

如果您想很好地打印或保存词典,请参阅How do I write JSON data to a file?

delete a["key_"]["key0a"]["sub_key2a"]