打印python嵌套字典的所有值的完整键路径

Print complete key path for all the values of a python nested dictionary

如果下面是我的嵌套字典,我希望递归地解析并打印所有值以及嵌套键的完整路径。

1
my_dict = {'attr':{'types':{'tag':{'name':'Tom', 'gender':'male'},'category':'employee'}}}

预期输出:

1
2
3
4
5
6
Key structure : my_dict["attr"]["types"]["tag"]["name"]
value :"Tom"
Key structure : my_dict["attr"]["types"]["tag"]["gender"]
value :"male"
Key structure : my_dict["attr"]["types"]["category"]
value :"employee"

我写了一个递归函数,但运行到这里:

1
2
3
4
5
6
7
8
9
10
11
12
13
my_dict = {'attr':{'types':{'tag':{'name':'Tom','gender':'male'},'category':'employee'}}}

def dict_path(path,my_dict):
    for k,v in my_dict.iteritems():
        if isinstance(v,dict):
            path=path+"_"+k
            dict_path(path,v)
        else:
            path=path+"_"+k
            print path,"=>",v

    return
dict_path("",my_dict)

输出:

_ attr_types_category=>员工_ attr_types_category_tag_gender=>男_ attr_types_category_tag_gender_name=>汤姆

在上面:对于男性,键结构不应包含"类别"如何保持正确的密钥结构?


您不应该更改dict_path()函数中的path变量:

1
2
3
4
5
6
7
def dict_path(path,my_dict):
    for k,v in my_dict.iteritems():
        if isinstance(v,dict):
            dict_path(path+"_"+k,v)
        else:
            print path+"_"+k,"=>",v
dict_path("",my_dict)

正如catavaran所提到的,您的问题是在for循环中向path变量添加新的路径组件造成的。您需要将新路径放入调用中,以便它被传递到下一个递归级别,并且不会干扰当前递归级别的for循环中后续项的路径。

这里有一个使用递归生成器的替代解决方案,而不是在dict_path函数中打印结果。(fwiw,我用print json.dumps(my_dict, indent=4)重新格式化字典)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
my_dict = {
   "attr": {
       "types": {
           "category":"employee",
           "tag": {
               "gender":"male",
               "name":"Tom"
            }
        }
    }
}

def dict_path(my_dict, path=None):
    if path is None:
        path = []
    for k,v in my_dict.iteritems():
        newpath = path + [k]
        if isinstance(v, dict):
            for u in dict_path(v, newpath):
                yield u
        else:
            yield newpath, v

for path, v in dict_path(my_dict):
    print '_'.join(path),"=>", v

输出

1
2
3
attr_types_category => employee
attr_types_tag_gender => male
attr_types_tag_name => Tom


只是在上面添加@catavaran代码。如果dict的值是list的话,如果list本身可以有dict或值,那么这个代码就可以帮上忙了。我刚把分隔符改为点。

1
2
3
4
5
6
7
8
9
def dict_path(path,my_dict):
    for k,v in my_dict.iteritems():
        if isinstance(v,list):
            for i, item in enumerate(v):
                dict_path( path +"." + k +"." + str(i), item)
        elif isinstance(v,dict):
            dict_path(path+"."+k,v)
        else:
            print path+"."+k,"=>", v

谢谢你的代码帮助了我。