Skip to content Skip to sidebar Skip to footer

Traverse A Nested Dictionary And Get The Path In Python?

I have a dictionary like: { 'checksum': 'b884cbfb1a6697fa9b9eea9cb2054183', 'roots': { 'bookmark_bar': { 'children': [ { 'date_added': '12989159740

Solution 1:

I had a slightly different use case from you: I needed to flatten a variable depth JSON structure representing client settings into key-value pairs for storage in a database. I couldn't get jsbueno's answer to work, and since I also needed something that could handle cases without children being explicitly listing or contained, I modified it to suit my needs:

def traverse(dic, path=None):
    ifnotpath:
        path=[]
    if isinstance(dic,dict):
        for x in dic.keys():
            local_path = path[:]
            local_path.append(x)
            for b in traverse(dic[x], local_path):
                 yield b
    else: 
        yieldpath,dic

The end result is i can pass in a JSON string like this to my script (with variable depths), which converts it to nested dicts:

{"servers":{"uat":{"pkey":true,"user":"testval","pass":true},"dev":{"pkey":true,"user":"testval","pass":true}}}

running the generator above against it creates a list that pretty-prints like this:

([u'servers', u'uat', u'pkey'], True)
([u'servers', u'uat', u'user'], u'testval')
([u'servers', u'uat', u'pass'], True)
([u'servers', u'dev', u'pkey'], True)
([u'servers', u'dev', u'user'], u'testval')
([u'servers', u'dev', u'pass'], True)

Which, using something like:

for x in traverse(outobj):
    pprint(('.'.join(x[0]),x[1]))

can then be transformed into the key-value pair format I want like so:

(u'servers.uat.pkey', True)
(u'servers.uat.user', u'testval')
(u'servers.uat.pass', True)
(u'servers.dev.pkey', True)
(u'servers.dev.user', u'testval')
(u'servers.dev.pass', True)

I know I'm posting this way after the accepted answer was accepted, but since the accepted answer didn't work for me, maybe this slight more structure-agnostic version will help someone else!

Solution 2:

Not shure if I got what you want, but you might want to do this:

def traverse(dic, path=None):
    ifnotpath:
        path = []
    for i in dic:
        local_path = path[:].append(i)
        if i['type'] == 'folder':
            for j in traverse(i['children'], local_path):
                yield j, local_path
        elif i['type'] == 'url':
            yield i, local_path

Now your function yields the item and a sequence of the keys to get to the item at a certain location.

Post a Comment for "Traverse A Nested Dictionary And Get The Path In Python?"