Добавить все значения в глубоко вложенный словарь

У меня есть глубоко вложенный словарь (произвольные ключи и значения), например:

data = {
    'a': {
        'path': '/a/a.txt'
    },
    'b': {
        'b1': {
            'path': '/b/b1/b1.txt'
        },
        'b2': {
            'path': '/b/b2/b2.txt'
        }
    }
    'c': {
        'c1': {
            'c12': {
                'path': '/c/c1/c12/c12.txt'
            }
        },
        'c2': {
            'c22': {
                'path': '/c/c1/c22/c22.txt'
            }
        },
        'c3': {
            'c32': {
                'path': '/c/c1/c32/c32.txt'
            }
        }
    }
    .
    .
    .
}

Моя цель - добавить к каждому значению в словаре определенный путь. Итак, в основном возьмите приведенные выше данные, обработайте их:

def prepend(value, data):
    return magic

data = prepend('predir/z', data)

и получившийся dict выглядит так:

data = {
    'a': {
        'path': 'predir/z/a/a.txt'
    },
    'b': {
        'b1': {
            'path': 'predir/z/b/b1/b1.txt'
        },
        'b2': {
            'path': 'predir/z/b/b2/b2.txt'
        }
    }
    'c': {
        'c1': {
            'c12': {
                'path': 'predir/z/c/c1/c12/c12.txt'
            }
        },
        'c2': {
            'c22': {
                'path': 'predir/z/c/c1/c22/c22.txt'
            }
        },
        'c3': {
            'c32': {
                'path': 'predir/z/c/c1/c32/c32.txt'
            }
        }
    }
    .
    .
    .
}

Я знаю, что могу использовать рекурсию для перебора dict следующим образом:

def prepend(directory, config):
    for k, v in config.items():
        if isinstance(v, dict):
            prepend(directory, v)
        else:
            # do something

Но я не могу изменить значения во время итерации. Любая помощь приветствуется! Благодарю вас!


person Xylot    schedule 17.05.2020    source источник
comment
что у вас есть в else: # do something ? Как вы пытаетесь изменить значение? Вы пытались изменить значение в config[k] вместо v?   -  person furas    schedule 17.05.2020


Ответы (2)


В ветке else просто добавьте префикс к существующему значению и сохраните его в ключе:

def prepend(directory, config):
    for k, v in config.items():
        if isinstance(v, dict):
            prepend(directory, v)
        else:
            config[k] = directory + v
    return config
person azro    schedule 17.05.2020
comment
Не уверен, как я пропустил это! Благодарю вас! - person Xylot; 17.05.2020

Вы должны использовать

else:
    config[k] = directory + config[k]

or

else:
    config[k] = directory + v

и он изменит значение непосредственно в исходном data, поэтому вам не нужен return config.


Кстати: если вы хотите сохранить исходные данные, вам придется создать new_config в функции.

def prepend(directory, config):
    new_config = {}
    for k, v in config.items():
        if isinstance(v, dict):
            new_config[k] = prepend(directory, v)
        else:
            new_config[k] = directory + v

    return new_config

new_data = prepend('predir/z', data)
print(data)
print(new_data)
person furas    schedule 17.05.2020