Creating a tree/deeply nested dict from an indented text file in python

后端 未结 4 1448
遥遥无期
遥遥无期 2020-12-05 12:17

Basically, I want to iterate through a file and put the contents of each line into a deeply nested dict, the structure of which is defined by the amount of whitespace at the

4条回答
  •  隐瞒了意图╮
    2020-12-05 12:34

    Here is a recursive solution. First, transform the input in the following way.

    Input:

    person:
        address:
            street1: 123 Bar St
            street2: 
            city: Madison
            state: WI
            zip: 55555
        web:
            email: boo@baz.com
    

    First-step output:

    [{'name':'person','value':'','level':0},
     {'name':'address','value':'','level':1},
     {'name':'street1','value':'123 Bar St','level':2},
     {'name':'street2','value':'','level':2},
     {'name':'city','value':'Madison','level':2},
     {'name':'state','value':'WI','level':2},
     {'name':'zip','value':55555,'level':2},
     {'name':'web','value':'','level':1},
     {'name':'email','value':'boo@baz.com','level':2}]
    

    This is easy to accomplish with split(':') and by counting the number of leading tabs:

    def tab_level(astr):
        """Count number of leading tabs in a string
        """
        return len(astr)- len(astr.lstrip('\t'))
    

    Then feed the first-step output into the following function:

    def ttree_to_json(ttree,level=0):
        result = {}
        for i in range(0,len(ttree)):
            cn = ttree[i]
            try:
                nn  = ttree[i+1]
            except:
                nn = {'level':-1}
    
            # Edge cases
            if cn['level']>level:
                continue
            if cn['level']level:
                rr = ttree_to_json(ttree[i+1:], level=nn['level'])
                dict_insert_or_append(result,cn['name'],rr)
            else:
                dict_insert_or_append(result,cn['name'],cn['value'])
                return result
        return result
    

    where:

    def dict_insert_or_append(adict,key,val):
        """Insert a value in dict at key if one does not exist
        Otherwise, convert value to list and append
        """
        if key in adict:
            if type(adict[key]) != list:
                adict[key] = [adict[key]]
            adict[key].append(val)
        else:
            adict[key] = val
    

提交回复
热议问题