#python #dictionary
Вопрос:
Рассмотрим этот входной словарь:
my_dict = { 'group1':{ 'type1': {'val1' : 45, 'val2' : 12, 'val3' : 65}, 'type2': {'val5' : 65, 'val6' : 132, 'val7' : 656}, }, 'group2':{ 'type3': {'val11' : 45, 'val12' : 123, 'val13' : 3}, 'type4': {'val51' : 1, 'val61' : 2, 'val71' : 3, }, }, }
Я хотел бы удалить последний «уровень» (тот, на котором есть только цифры) и получить что-то вроде:
new_dict = { 'group1':{ 'type1': ['val1', 'val2', 'val3'], 'type2': ['val5', 'val6', 'val7'], }, 'group2':{ 'type3': ['val11', 'val12', 'val13'], 'type4': ['val51', 'val61', 'val71'], }, }
В настоящее время я делаю это вручную, зацикливаясь и так далее, но мне интересно, есть ли способ сделать это более эффективно.
Комментарии:
1. Чего вы хотите достичь? Я мог видеть, что оба они одинаковы, просто отличаются по своему типу. У одного есть диктант, а у другого список ключей
Ответ №1:
Если в вашем словаре нет фиксированного числа уровней вложенности, вы можете написать рекурсивную функцию для этого:
def stripBottom(d): if not isinstance(d,dict): return d elif not any(isinstance(v,dict) for v in d.values()): return list(d) else: return {k:stripBottom(v) for k,v in d.items()}
Выход:
my_dict = { 'group1':{ 'type1': {'val1' : 45, 'val2' : 12, 'val3' : 65}, 'type2': {'val5' : 65, 'val6' : 132, 'val7' : 656}, }, 'group2':{ 'type3': {'val11' : 45, 'val12' : 123, 'val13' : 3}, 'type4': {'val51' : 1, 'val61' : 2, 'val71' : 3, }, }, } print(stripBottom(my_dict)) {'group1': {'type1': ['val1', 'val2', 'val3'], 'type2': ['val5', 'val6', 'val7']}, 'group2': {'type3': ['val11', 'val12', 'val13'], 'type4': ['val51', 'val61', 'val71']}}
Если в вашем словаре есть переменные уровни вложенности или если вы хотите понизить определенный уровень, вам нужно будет добавить параметр в функцию:
def stripBottom(d,level=0): if not isinstance(d,dict): return d elif level == 0: return list(d) else: return {k:stripBottom(v,level-1) for k,v in d.items()} print(stripBottom(my_dict,1)) {'group1': ['type1', 'type2'], 'group2': ['type3', 'type4']}
Ответ №2:
Вы не приводите пример фактического кода, который вы используете для изменения диктанта, но, скорее всего, вам всегда понадобится 2 уровня цикла для перебора групп, а затем типов. Что-то вроде:
newdict = {} for k, grp in my_dict.items(): newdict[k] = {} for typ, val in grp.items(): newdict[k][typ] = list(val)
Один из вариантов повышения эффективности состоит в том, чтобы не предварительно вычислять эти обновленные значения, а вместо этого, когда вы начнете использовать данные «группы», оберните выходные данные list
в этот момент. (Хотя, очевидно, вы все равно будете повторять, когда используется диктант, чтобы получить эти вложенные диктанты).