Удалите нижний уровень во вложенном словаре python

#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 в этот момент. (Хотя, очевидно, вы все равно будете повторять, когда используется диктант, чтобы получить эти вложенные диктанты).