Доступ к вложенному словарю по списку ключей
Есть словарь и список ключей, по которому нужно получить значение из первого
dictonary = {
'level1A': {'level2A': 'valueAA', 'level2B': 'valueAB'},
'level1B': {'level2A': 'valueBA', 'level2B': 'valueBB'}
}
keylist = ['level1B', 'level2A']
Вопрос: как из 'value2A' сделать любое другое значение? По возможности используйте dict[key] = 'value', чтобы я мог настроить добавление элемента dict[addedkey] = 'addedvalue' и его удаление del dict[delkey] или подскажите другие варианты это сделать (это мне тоже надо, забыл сразу указать, а создавать новый вопрос как по мне не очень логично).
dictonary['level1B']['level2B'] = 'newvalue' #это работает, но нужно знать уровень вложенности
dictonary[keylist] = 'newvalue' #нужен рабочий аналог этого действия, т. к. "TypeError: unhashable type: list"
Вложенность dictonary и длина keylist могут быть любыми.
Я пробовал получить каждую вложенность в список, изменить самую глубокую и "собрать" словарь обратно, но либо я накосячил в коде, либо метод не работает. Вот метод для получения вложенности (он рабочий):
def getlevel(dictonary, keylist):
res = dictonary
for d in keylist:
res = res[d]
return dictonary
P.S. Имена переменных любые, главное, чтобы я понял, где словарь, а где список ключей.
EDIT: На самом деле, задача состоит в возможности не только изменения, но и добавления и удаления ключей и значений.
EDIT2:В списке ключей каждый следующий ключ для следующего "уровня" словаря. Первый элемент - ключ для первого "уровня", второй для второго и т.д. И каждый новый "уровень" - значение ключа на предыдущем "уровне". И значение последнего ключа в списке ключей не обязано быть определенным типом данных; это тоже может быть словарь, но там я разберусь. "Уровень" - словарь-значение у текущего ключа в списке ключей. Первый "уровень" - "корневой словарь", у меня в нём определены level1A и level1B
Ответы (4 шт):
@proger786, Если keylist организован как список, содержащий список 2ух ключей для доступа то так:
dictonary = {
'level1A': {'level2A': 'valueAA', 'level2B': 'valueAB'},
'level1B': {'level2A': 'valueBA', 'level2B': 'valueBB'}}
keylist = [['level1B', 'level2A']]
def get_data(tuplekey, dict_data):
key1, key2 = tuplekey
return dict_data[key1][key2]
for element_lst in keylist:
print(get_data(tuplekey=element_lst, dict_data=dictonary))
Если не так, но напишите поподробнее про keylist
Спускаемся по вложеным словарям, кроме последнего. В последний словарь по последнему ключу записываем значение:
def set_value(d, keys, value):
for k in keys[:-1]:
d = d[k]
d[keys[-1]] = value
Можно создавать словари на лету:
def set_value(d, keys, value):
for k in keys[:-1]:
d = d.setdefault(k, {})
d[keys[-1]] = value
Этот код ищет во всех вложенных словарях.
getval() возвращает первое найденное совпадение (у вас в словарях ключи дублируются):
dictionary = {
'level1A': {'level2A': 'valueAA', 'level2B': {'level3': 'value3'}},
'level1B': {'level2A': 'valueBA', 'level2B': 'valueBB'}}
keylist = ['level1B', 'level2A', 'level2B', 'level3', 'level4']
def getval(k, d=dictionary):
res = None
if k in d: return d[k]
for i in d:
if isinstance(d[i], dict): res = getval(k, d[i])
if res: return res
for i in keylist:
print(f'{i} = {getval(i)}')
результат:
level1B = {'level2A': 'valueBA', 'level2B': 'valueBB'}
level2A = valueAA
level2B = {'level3': 'value3'}
level3 = value3
level4 = None
До конца не понял что вы хотите в итоге получить. Попробуйте это:
dictionary = {
'level1A': {'level2A': 'valueAA', 'level2B': 'valueAB'},
'level1B': {'level2A': {'level3': 'value3'}, 'level2B': 'valueBB'}
}
keylist = ['level1B', 'level2A', 'level3']
def func(k,d=dictionary):
if type(d)==dict: v = d.get(k.pop(0),-1)
else: return -1
return v if not k else func(k,v)
результат (-1 если значение не найдено):
func(keylist) # 'value3'