Home > other >  Unnest list of dictionaries to key value and subdicts
Unnest list of dictionaries to key value and subdicts

Time:01-08

I have a dict with nested lists of dictionaries, as below:

{'data1': [{'data2': 'value2'},
  {'data3': [{'data4': 'value4'},
    {'data5': [{'data6': 'value6'}, {'data7': 'value7'}]}]}]}

I want to obtain:

{'data1': {'data2': 'value2',
  'data3': {'data4': 'value4',
   'data5': {'data6': 'value6', 'data7': 'value7'}}}}

So there are 2 tasks, convert single sub dicts to key:value ({'data2':'value2'} to 'data2':'value2') and convert lists of dicts to nested dicts ({'data5': [{'data6':'value6'},{'data7' : 'value7'}]} to 'data5': {'data6':'value6','data7' : 'value7'}).

This is a deeply nested recursive dictionary with multiple levels.

I was trying something like this:

def flat(j): 
    if not isinstance(j, (dict, list)): 
        return j 
    if isinstance(j, dict): 
        p=list(j.values()) 
        f=list(j.keys()) 
        tipo=type(p[0]).__name__ 
        if tipo=="str": 
             (Do something) 
    if isinstance(j, list): 
        return [flat(v) for v in j] 
    return {k: flat(v) for k, v in j.items()} 

in order to flat the single dictionaries but I found the problem of deletting the sub dict and add the key:value. For sure there is another post with how to convert the list to nested dictionaries

CodePudding user response:

You can use a recursive approach and handle each value depending on whether this is a dict, list, or something else:

def unnest(x):
    if isinstance(x, dict):
        return {k: unnest(v) for k,v in x.items()}
    elif isinstance(x, list):
        return {k:unnest(v) for e in x for k,v in unnest(e).items()}
    else:
        return x

# assuming the input dictionary as "d"
unnest(d)

output:

{'data1': {'data2': 'value2',
           'data3': {'data4': 'value4',
                     'data5': {'data6': 'value6', 'data7': 'value7'}
                     },
           },
}

NB. the requirement here is that lists only contain dictionaries, if not you need to add a condition

CodePudding user response:

You can use a recursive generator function:

data = {'data1': [{'data2': 'value2'}, {'data3': [{'data4': 'value4'}, {'data5': [{'data6': 'value6'}, {'data7': 'value7'}]}]}]}
def unnest(d):
  if isinstance(d, list):
    yield from [j for k in d for j in unnest(k)]
  else:
    for a, b in d.items():
       yield (a, b if not isinstance(b, (list, dict)) else dict(unnest(b)))

result = dict(unnest(data))

Output:

{'data1': {'data2': 'value2', 'data3': {'data4': 'value4', 'data5': {'data6': 'value6', 'data7': 'value7'}}}}

This will work on both lists and dictionaries.

  •  Tags:  
  • Related