Convert list of key/value pairs to nested dictionary

Question:

Input data:

data = [
    ['QR', ''],
    ['Cust', ''],
    ['fea', 'restroom'],
    ['chain', 'pa'],
    ['store', 'cd'],
    ['App', ''],
    ['End', 'EndnR'],
    ['Request', '0'],
    ['Sound', '15'],
    ['Target', '60'],
    ['Is', 'TRUE']
]

I want to turn this into a dictionary, and each blank value indicates the start of a new, nested sub-dictionary.

Desired output:

{
    'QR': {
            'Cust': { 
                'fea': 'restroom ',
                'chain': 'pa',
                'store': 'cd'
            },
            'App': {
                'End': 'EndnR',
                'Request': '0',
                'Sound': '15',
                'Target': '60',
                'Is': 'true'
            },
    }
}

Here is my code so far:

from collections import defaultdict
res = defaultdict(dict)
for i in data:
    res[i[0]] = i[1]
print(res)

But it only creates a flat dictionary with some blank values, not a nested dictionary.

Asked By: coder

||

Answers:

try this:

result = {}
nbr_keys = 0
keys = [ item[0] for item in data if item[1] == "" ]

for index, item in enumerate(data):
    
    if index == 0:
        if item[1] == "":
            key = item[0]
            di[item[0]] = {}
    else:
        
        if item[1] == "":
            di[key].update({item[0]: {}})
            nbr_keys +=1
            
        else:
            di[key][keys[nbr_keys]].update({item[0]: item[1]})

which outputs this:

{'QR': {'Cust': {'fea': 'restroom', 'chain': 'pa', 'store': 'cd'},
  'App': {'End': 'EndnR',
   'Request': '0',
   'Sound': '15',
   'Target': '60',
   'Is': 'TRUE'}}}
Answered By: kev_ta

Consider the following approach using itertools.groupby function:

from itertools import groupby

data=[['QR', ''], ['Cust', ''], ['fea', 'restroom'], ['chain', 'pa'], ['store', 'cd'], ['App', ''], ['End', 'EndnR'],
      ['Request', '0'], ['Sound', '15'], ['Target', '60'], ['Is', 'TRUE']]

def l_to_dict(data):
    store = []
    for new_d, gr in groupby(data, lambda x: x[1] == ''):
        if not store:
            store.append({})
        if new_d:   # having new nested dict case
            for k, v in gr:
                store[-1][k] = {}
                store.append(store[-1][k])  # append last empty dict to the back
        else:
            curr = store[-1] if len(store) == 1 else store.pop()
            for k, v in gr:
                curr[k] = v
    return store[0]


pprint(l_to_dict(data), width=10, sort_dicts=False)

{'QR': {'Cust': {'fea': 'restroom',
                 'chain': 'pa',
                 'store': 'cd'},
        'App': {'End': 'EndnR',
                'Request': '0',
                'Sound': '15',
                'Target': '60',
                'Is': 'TRUE'}}}
Answered By: RomanPerekhrest
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.