如何更改嵌套键的值

0 投票
2 回答
49 浏览
提问于 2025-04-12 20:10

目标:我想要修改一个嵌套字典的值,但我事先并不知道这个字典的具体结构

这里有一个示例输入字典:

example_dict = {
    'key1': 'value1',
    'key2': {
        'key2a': 'value2a'
    },
    'key3': {
        'key3a': {
            'key3aa': 'value3aa',
            'key3ab': 'value3ab',
            'key3ac': 'value3ac'
        },
        'key3b': [
            'value3b1',
            'value3b2'
        ]
    },
}

期望的输出:

example_dict = {
    'key1': 'changed_value1',
    'key2': {
        'key2a': 'changed_value2a'
    },
    'key3': {
        'key3a': {
            'key3aa': 'changed_value3aa',
            'key3ab': 'changed_value3ab',
            'key3ac': 'changed_value3ac'
        },
        'key3b': [
            'changed_value3b1',
            'changed_value3b2'
        ]
    },
}

我尝试过的:首先,我在递归地查找字典中的键和值。

def recursive(src, so_far=()):
    if isinstance(src, dict):
        for key, value in src.items():
            yield from recursive(value, so_far + (key,))
    elif isinstance(src, list):
        for item in src:
            yield from recursive(item, so_far)
    else:
        yield ' '.join(so_far + (src,))

for line in recursive(example_dict):
    print(line)

这段代码输出:

key1 value1
key2 key2a value2a
key3 key3a key3aa value3aa
key3 key3a key3ab value3ab
key3 key3a key3ac value3ac
key3 key3b value3b1
key3 key3b value3b2

现在我知道了字典的结构,我想要编辑这些值。

但我在这里遇到了困难。

我知道可以通过以下方式来改变字典的值:

example_dict['key1'] = 'changed_value1'

但是我该如何使用循环来改变嵌套键的值呢?

换句话说,我想生成以下命令:

example_dict['key1'] = 'changed_value1'
example_dict['key2'] ['key2a] = 'changed_value2a'
example_dict['key3'] ['key3a] ['key3aa'] = 'changed_value3aa'
example_dict['key3'] ['key3a] ['key3ab'] = 'changed_value3ab'
example_dict['key3'] ['key3a] ['key3ac'] = 'changed_value3ac'
example_dict['key3'] ['key3b] = 'changed_value3b1', 'changed_value3b2'

2 个回答

0

这样怎么样呢?当然,你需要根据自己的需求来修改一下 modifier;下面的代码输出是:

{'key1': 'value1',
 'key2': {'key2a': 'value2a'},
 'key3': {'key3a': {'key3aa': 'value3aa modified',
                    'key3ab': 'value3ab modified',
                    'key3ac': 'value3ac modified'},
          'key3b': ['value3b1 modified', 'value3b2 modified']}}
def modify_recursively_in_place(d, modifier, path=()):
    for k, v in d.items():
        if isinstance(v, dict):
            modify_recursively_in_place(v, modifier, (*path, k))
        elif isinstance(v, list):
            for i, e in enumerate(v):
                if isinstance(e, (dict, list)):
                    modify_recursively_in_place(e, modifier, (*path, k, i))
                else:
                    v[i] = modifier(v[i], (*path, k, i))
        else:
            d[k] = modifier(v, (*path, k))


# ---


def modifier(value, path):
    if isinstance(path[-1], str) and path[-1].startswith("key3a"):
        value = f"{value} modified"
    if isinstance(path[-1], int):
        value = f"{value} modified"
    return value


example_dict = {
    "key1": "value1",
    "key2": {
        "key2a": "value2a",
    },
    "key3": {
        "key3a": {
            "key3aa": "value3aa",
            "key3ab": "value3ab",
            "key3ac": "value3ac",
        },
        "key3b": [
            "value3b1",
            "value3b2",
        ],
    },
}


modify_recursively_in_place(example_dict, modifier)

print(example_dict)
0

除了键和值对,还要返回父级。

def recursive(src, so_far=()):
    if isinstance(src, dict):
        for key, value in src.items():
            if isinstance(value, dict) or isinstance(value, list):
                yield from recursive(value, so_far + (key,))
            else:
                yield src, key, value
    elif isinstance(src, list):
        for index, value in enumerate(src):
            if isinstance(value, dict) or isinstance(value, list):
                yield from recursive(value, so_far + (index,))
            else:
                yield src, index, value
    else:
        raise ValueError

for parent, key, value in recursive(example_dict):
    parent[key] = "modified " + value

撰写回答