#python #list #dictionary #flatten
Вопрос:
У меня есть словарь:
dict1 = {
'conf1' : {'subconf11' : True, 'subconf12' : False},
'conf2' : False,
'conf3' : {'subconf31' : True, 'subconf32' : False, 'subconf33' : False},
'conf4' : 'On'
}
Я хочу свести его к списку кортежей, чтобы:
list1 = [
('conf1',('subconf11',True)),
('conf1',('subconf12',False)),
('conf2',False),
('conf3',('subconf31',True)),
('conf3',('subconf32',False)),
('conf3',('subconf33',False)),
('conf4','On')
]
Я попробовал что-то вроде:
primary_conf_list = list(dict1.keys())
list2 = [(i,list[dict1[i].items()]) for i in primary_conf_list]
Но по понятным причинам это приводит меня к ошибке для тех, где значение не является словарем, а либо bool, либо строковым значением. Например dict1['conf2']
, dict1['conf4']
И.
Вот точное сообщение об ошибке:
AttributeError: 'bool' object has no attribute 'items'
Пожалуйста, помогите мне достичь этого.
Комментарии:
1. Вам нужны вложенные циклы для создания кортежа для каждого элемента во вложенных словарях.
Ответ №1:
Вы должны проверить, является ли значение словарем. Если это так, используйте вложенный цикл для добавления элементов в результат для каждого элемента.
list2 = []
for key, val in dict1.items():
if isinstance(val, dict):
for subkey, subval in val.items():
list2.append((key, (subkey, subval)))
else:
list2.append(key, val)
Комментарии:
1. @Barmer спасибо, это то, чего я хотел. Один вопрос, насколько мне известно, чем
isinstance(val, dict)
отличается отtype(val) is dict
поведения. Я видел случаи (особенно сценарии cpython), когдаtype()
совпадение не срабатывало. Но isinstance() работает почти для всех практических целей.2.
isinstance()
будет работать для подклассов, таких какdefaultdict
.3. @Barmer Не могли бы вы, пожалуйста, преобразовать свой ответ в рекурсивный код для словаря словарей. Например
subconf31
, может быть сам словарь словарей. пример:'subconf31' : { 'subconf311' : { 'subconf3111' : True, 'subconf31112' : False}, 'subconf312' : True}