在Python中使用键的有序列表遍历带列表的嵌套字典
我有一个嵌套的在Python中使用键的有序列表遍历带列表的嵌套字典,python,tree,Python,Tree,我有一个嵌套的dict,如下所示: d = {'A': [{'B': [{'C': [{'D1':[]}, {'D2': []}]}]}]} # just an example 我得到的列表/路径如下: l = ['A','B','C','D1'] from copy import deepcopy def walk_dict(ld, path): if isinstance(path, str): path = path.split() t = deepc
dict
,如下所示:
d = {'A': [{'B': [{'C': [{'D1':[]}, {'D2': []}]}]}]} # just an example
我得到的列表/路径如下:
l = ['A','B','C','D1']
from copy import deepcopy
def walk_dict(ld, path):
if isinstance(path, str):
path = path.split()
t = deepcopy(ld)
for key in path:
if isinstance(t, list):
try:
t = [d for d in t if key in d][0]
except IndexError:
return
try:
t = t[key]
except KeyError:
return
else:
return t
def main():
d = {'A': [{'B': [{'C': [{'D1':['values of D1']}, {'D2': "I'm D2"}]}]}]}
a = 'A B C D1'
print(walk_dict(d, a))
a = 'A B C D2'
print(walk_dict(d, a))
a = 'A B C D3'
print(walk_dict(d, a))
a = 'A B1 C D3'
print(walk_dict(d, a))
if __name__ == '__main__':
main()
我想沿着dict
中的路径,检索D1
的对应值。为此,我编写了以下程序:
def find_dict(ld, key):
# we can assume that 'ld' has dicts each of which has unique key
for d in ld:
if key not in d:
continue
return d
def walk_dict(d,path):
temp = None
for i,n in enumerate(path):
if i == 0:
temp = d.get(n)
elif i < (len(path)-1):
temp = find_dict(temp, n)
temp = temp.get(n)
else: # last item
temp = find_dict(temp, n)
print('Found it!')
print(i,n)
print(temp.get(n))
return temp.get(n)
d = {'A': [{'B': [{'C': [{'D1':[]}, {'D2': []}]}]}]}
l = ['A','B','C','D1'] # successfully retrieved the value of 'D1'
walk_dict(d,l)
l = ['A','B','C','D2'] # successfully retrieved the value of 'D2'
walk_dict(d,l)
l = ['A','B','C','D3'] # get NoneType error as expected because 'D3' does not exist
walk_dict(d,l)
def find_dict(ld,key):
#我们可以假设'ld'有dict,每个dict都有唯一的密钥
对于ld中的d:
如果钥匙不在d中:
持续
返回d
def步行指令(d,路径):
温度=无
对于枚举(路径)中的i,n:
如果i==0:
温度=d.get(n)
elif i<(透镜(路径)-1):
温度=查找目录(温度,n)
温度=温度获取(n)
其他:#最后一项
温度=查找目录(温度,n)
打印('找到了!')
打印(i,n)
打印(临时获取(n))
返回温度获取(n)
d={'A':[{'B':[{'C':[{'D1':[]},{'D2':[]}]}
l=['A'、'B'、'C'、'D1']#成功检索到'D1'的值
步行(d,l)
l=['A'、'B'、'C'、'D2']#成功检索到'D2'的值
步行(d,l)
l=['A'、'B'、'C'、'D3']#按预期获取非类型错误,因为'D3'不存在
步行(d,l)
我想知道是否有更好的方法来实现这一点。我觉得这种方法有点过于冗长,甚至可能有bug潜伏
提前感谢您的回答/建议 像这样走路怎么样:
l = ['A','B','C','D1']
from copy import deepcopy
def walk_dict(ld, path):
if isinstance(path, str):
path = path.split()
t = deepcopy(ld)
for key in path:
if isinstance(t, list):
try:
t = [d for d in t if key in d][0]
except IndexError:
return
try:
t = t[key]
except KeyError:
return
else:
return t
def main():
d = {'A': [{'B': [{'C': [{'D1':['values of D1']}, {'D2': "I'm D2"}]}]}]}
a = 'A B C D1'
print(walk_dict(d, a))
a = 'A B C D2'
print(walk_dict(d, a))
a = 'A B C D3'
print(walk_dict(d, a))
a = 'A B1 C D3'
print(walk_dict(d, a))
if __name__ == '__main__':
main()
输出:
['values of D1']
I'm D2
None
None
all cases passed
我使用了递归方法
d = {'A': [{'B': [{'C': [{'D1':'xyz'}, {'D2': []}]}]}]}
l = ['A','B','C','D1']
output = []
def find_path(dict_obj,key=0):
for k,v in dict_obj.items():
if k == l[key]:
if key == len(l)-1:
output.append(v)
return
if isinstance(v,dict):
find_path(v, key+1)
elif isinstance(v,list):
for i,item in enumerate(v):
if isinstance(item,dict):
find_path(item,key+1)
find_path(d)
print(output[0] if output else None)
产出:
l = ['A','B','C','D1']
# xyz
l = ['A','B','C']
# [{'D1': 'xyz'}, {'D2': []}]
l = ['A','B','C','D3']
# None
l = ['A','B','C','D2']
# []
可以使用此递归函数:
d = {'A': [{'B': [{'C': [{'D1':[]}, {'D2': []}]}]}]} # just an example
def walk(_d, path):
a, *b = path
if isinstance(_d, list):
_d = [i for i in _d if a in i]
if not _d:
return None
_d = _d[0]
return _d[a] if not b else walk(_d[a], b)
tests = [[['A','B','C','D1'], []], [['A','B','C','D2'], []], [['A','B','C','D3'], None]]
for a, b in tests:
assert walk(d, a) == b
print('all cases passed')
输出:
['values of D1']
I'm D2
None
None
all cases passed
以下是当前答案的时间安排。计时和输入设置的源代码可以作为要点找到
这看起来是一种更清洁的解决方案。:)你为什么要做一份临时记录的浅显副本?另一个后续问题:如果我想在
D2
中添加另一个字符串,比如说,“我是D2的兄弟”
,这样它就会反映在d
(sourcedict
)中,进行浅拷贝会影响吗?谢谢你的帮助!对于那些想使用列表而不是字符串作为路径的人,我分享了Waket的解决方案@user1330974的一个稍微修改过的代码,我用deepcopy
编辑了答案。感谢你提供了一个简洁的递归解决方案!我很少在编码时想到递归方法,因为对我来说,很难想象它们。但我知道它们很简洁:)我仍在等待其他人插话,但根据时间安排,韦克特的回答比你的答案快了几分钟,他的回答也正确。所以我可以接受他的回答。希望你不介意。:)如果您对每个答案的性能感兴趣,我在下面的答案中添加了计时。非常感谢您不厌其烦地提供运行时分析!今天我从你那里学到了如何做一个快速而酷的运行时测试。因为它很酷,我把它存档在Wayback机器中。:)@user1330974很高兴为您提供帮助!