我有一个嵌套的字典,如下所示。
myTodo= {
'taskid': '10',
'taskstatus': 'in progress',
'Kitchen':
{
'Stove':{
'LED1':
{
'taskid': '11',
'taskstatus':'running'
},
'LED2':
{
'taskid': '12',
'taskstatus':'off',
'LEDSub':
{
'taskid': '13',
'taskstatus':'stable',
'LEDSub2':
{
'taskid': '14',
'taskstatus':'burnt'
}
}
},
'LED3':
{
'taskid': '15',
'taskstatus':'new'
}
},
//other nested layers
}
我有一个python方法,该方法根据键向我返回到达“值”的路由。 该方法如下所示。
def route(myTodo, id):
q = list()
q.append((list(), myTodo))
while q:
this_key_chain, this_v = reverse_linked_q.pop()
# finish search if found the id
if this_v == id:
return this_key_chain
# not found. keep searching
try:
items = this_v.items()
except AttributeError:
continue
for k, v in items:
q.append((this_key_chain + [k], v))
raise KeyError
此方法根据键返回路线。因此,如果我route(myTodo, "11")
,它将返回列表keyroute = [“ Kitchen”,“ Stove”,“ LED1”,“ taskid”]。
然后我从关键路由列表中删除“ taskid”,并将该列表发送到以下方法。
def createOutputDic(keyroute, myTodo):
for k in keyroute:
myTodo = myTodo.get(k)
return j
对于route(myTodo, "11")
,createOutputDic(keyroute,myTodo)
的输出为
{
'taskid': '11',
'taskstatus':'running'
}
以route(myTodo, "12")
拨打电话时出现问题。我希望得到
{ 'taskid': '12',
'taskstatus':'off'
}
但结果是
{
'taskid': '12',
'taskstatus':'off',
'LEDSub':
{
'taskid': '13',
'taskstatus':'stable',
'LEDSub2':
{
'taskid': '14',
'taskstatus':'burnt'
}
}
我只想得到
{ 'taskid': '12',
'taskstatus':'off'
}
但是我不明白为什么当前的route(..)方法无法做到这一点。 字典可能嵌套得很深,我想有一个通用的方法。 有人可以帮助我,或指导我以更好的方式解决此问题吗?任何帮助表示赞赏。
答案 0 :(得分:2)
您可以对generator使用递归:
def get_data(d, val):
if any(c == val for c in d.values()):
yield {i:d.get(i) for i in ['taskid', 'taskstatus']}
else:
for i in d.values():
if isinstance(i, dict):
yield from get_data(i, val)
myTodo = {'taskid': '10', 'taskstatus': 'in progress', 'Kitchen': {'Stove': {'LED1': {'taskid': '11', 'taskstatus': 'running'}, 'LED2': {'taskid': '12', 'taskstatus': 'off', 'LEDSub': {'taskid': '13', 'taskstatus': 'stable', 'LEDSub2': {'taskid': '14', 'taskstatus': 'burnt'}}}, 'LED3': {'taskid': '15', 'taskstatus': 'new'}}}}
result = list(get_data(myTodo, '12'))
print(result if not result else result[0])
输出:
{'taskid': '12', 'taskstatus': 'off'}
要格式化输出,将使用所需输出中包含的相同键创建字典。 yield
语句创建一个生成器对象,该生成器对象指向内存中其他对象,这些对象在运行中“已生成”。基于生成器的解决方案比使用return
更加干净,因为后者需要在第二个for
循环之外创建一个列表,每个get_data
调用返回的结果都可以使用该列表附加到。最终,在每次yield
调用中仅使用get_data
会更清洁。