[英]Python: How to convert nested lists inside nested dicts into dicts
所以我有這個命令:
di = {'Type': ['Something1'],
'details': [{'detail': [{'category': ['Stuff1'], 'value': ['Value1']},
{'category': ['Stuff2'], 'value': ['Value2']},
{'category': ['Stuff3'], 'value': ['Value3']},
{'category': ['Stuff3'], 'value': ['Value3']},
{'category': ['Stuff4'], 'value': ['Value4']}]}],
'timestamp': ['2018-01-22 07:10:41']}
並希望將除不包含其他 dict
list of dicts
任何dict
list
以外的任何list of dicts
轉換為dict
以便最終結果為:
{'Type': 'Something1',
'details': {'detail': [{'category': 'Stuff1', 'value': 'Value1'},
{'category': 'Stuff2', 'value': 'Value2'},
{'category': 'Stuff3', 'value': 'Value3'},
{'category': 'Stuff3', 'value': 'Value3'},
{'category': 'Stuff4', 'value': 'Value4'}]},
'timestamp': '2018-01-22 07:10:41'}
因此,從本質上講,對於任何值為單個項目list
,該值都應刪除list
組件。
我嘗試使用以下遞歸函數未成功:
def delistdict(dicto):
delisted = {}
for k,v in dicto.items():
if isinstance(v, list) and len(v) == 1:
delisted[k] = v[0]
else:
delisted[k] = delistdict(v)
return {k:v if len(v) == 1 else v for k,v in delisted.items()}
它之所以失敗,是因為它僅刪除了{'detail': [(...)]
list
的第一個實例(因此僅刪除了外部[(...)]列表),但沒有遞歸到其余項。 因此,運行腳本后,我的結果如下所示:
{'Type': 'Something1',
'details': {'detail': [{'category': ['Stuff1'], 'value': ['Value1']},
{'category': ['Stuff2'], 'value': ['Value2']},
{'category': ['Stuff3'], 'value': ['Value3']},
{'category': ['Stuff3'], 'value': ['Value3']},
{'category': ['Stuff4'], 'value': ['Value4']}]},
'timestamp': '2018-01-22 07:10:41'}
應該發生的是,應該將value
和category
鍵中的單個值轉換為string
s,而不是將其保留為list
單個項。
有什么想法我做錯了嗎?
您可以嘗試以下方法:
di = {'timestamp': ['2018-01-22 07:10:41'], 'Type': ['Something1'], 'details': [{'detail': [{'category': ['Stuff1'], 'value': ['Value1']}, {'category': ['Stuff2'], 'value': ['Value2']}, {'category': ['Stuff3'], 'value': ['Value3']}, {'category': ['Stuff3'], 'value': ['Value3']}, {'category': ['Stuff4'], 'value': ['Value4']}]}]}
def flatten(d):
return {a:b[0] if len(b) == 1 and isinstance(b[0], str) else (flatten(b[0]) if len(b) == 1 and isinstance(b[0], dict) else [flatten(c) for c in b]) for a, b in d.items()}
輸出:
{'timestamp': '2018-01-22 07:10:41', 'Type': 'Something1', 'details': {'detail': [{'category': 'Stuff1', 'value': 'Value1'}, {'category': 'Stuff2', 'value': 'Value2'}, {'category': 'Stuff3', 'value': 'Value3'}, {'category': 'Stuff3', 'value': 'Value3'}, {'category': 'Stuff4', 'value': 'Value4'}]}}
非綜合性解決方案:
def flatten(d):
new_d = {}
for a, b in d.items():
if len(b) == 1 and isinstance(b[0], str):
new_d[a] = b[0]
elif len(b) == 1 and isinstance(b[0], dict):
new_d[a] = flatten(b[0])
else:
temp_list = []
for c in b:
temp_list.append(flatten(c))
new_d[a] = temp_list
return new_d
輸出:
{'timestamp': '2018-01-22 07:10:41', 'Type': 'Something1', 'details': {'detail': [{'category': 'Stuff1', 'value': 'Value1'}, {'category': 'Stuff2', 'value': 'Value2'}, {'category': 'Stuff3', 'value': 'Value3'}, {'category': 'Stuff3', 'value': 'Value3'}, {'category': 'Stuff4', 'value': 'Value4'}]}}
我沒有花時間來優化代碼,但我修改了您的原始函數來解決問題:
def delistdict(dicto):
delisted = {}
for k, v in dicto.items():
if isinstance(v, list):
lst = []
for i in v:
if isinstance(i, dict):
lst.append(delistdict(i))
else:
lst.append(i)
delisted[k] = lst[0] if len(lst) == 1 else lst
elif isinstance(v, dict):
delisted[k] = delistdict(v)
else:
delisted[k] = v
return {k:v if len(v) == 1 else v for k,v in delisted.items()}
{'Type': 'Something1',
'details': {'detail': [{'category': 'Stuff1', 'value': 'Value1'},
{'category': 'Stuff2', 'value': 'Value2'},
{'category': 'Stuff3', 'value': 'Value3'},
{'category': 'Stuff3', 'value': 'Value3'},
{'category': 'Stuff4', 'value': 'Value4'}]},
'timestamp': '2018-01-22 07:10:41'}
問題是您的函數假定所有list
都應為len
1,否則它僅返回已刪除list
的字典,該字典仍具有未處理的嵌套list
s。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.