Ven
Ven

Reputation: 57

How to flatten a list of dicts with nested dicts

I want to flatten a list of dict but having issues,

let's say i have a list of dict as,

d = [{'val': 454,'c': {'name': 'ss'}, 'r': {'name1': 'ff'}},{'val': 'ss', 'c': {'name': 'ww'}, 'r': {'name1': 'ff'}}, {'val': 22,'c': {'name': 'dd'}, 'r': {'name1': 'aa'}}]

And the output I'm trying to get is,

d = [{'val': 454,'name': 'ss', 'name1': 'ff'},{'val': 'ss','name': 'ww', 'name1': 'ff'},{'val': 22, 'name': 'dd', 'name1': 'aa'}]

For which I'm using the following function,

def flatten(structure, key="", flattened=None):
    if flattened is None:
        flattened = {}
    if type(structure) not in(dict, list):
        flattened[key] = structure
    elif isinstance(structure, list):
        for i, item in enumerate(structure):
            flatten(item, "%d" % i, flattened)
    else:
        for new_key, value in structure.items():
            flatten(value, new_key, flattened)
    return flattened

Now, the issue I have is, it's only generating the first element in the dict

Upvotes: 0

Views: 752

Answers (2)

Egal
Egal

Reputation: 1474

You should initialize flattened to the same type as structure if it's None, and pass None when recursing at the list case:

def flatten_2(structure, key="", flattened=None):
    if flattened is None:
        flattened = {} if isinstance(structure, dict) else []
    if type(structure) not in(dict, list):
        flattened[key] = structure
    elif isinstance(structure, list):
        for i, item in enumerate(structure):
            flattened.append(flatten(item, "%d" % i))
    else:
        for new_key, value in structure.items():
            flatten(value, new_key, flattened)
    return flattened

In [13]: flatten_2(d)
Out[13]: 
[{'name': 'ss', 'name1': 'ff', 'val': 454},
 {'name': 'ww', 'name1': 'ff', 'val': 'ss'},
 {'name': 'dd', 'name1': 'aa', 'val': 22}]

This of course only works for a limited type of data.

Upvotes: 0

Ma0
Ma0

Reputation: 15204

You are probably initializing something in the wrong place. Take a look at the code below:

d = [{'val': 454, 'c': {'name': 'ss'}, 'r': {'name1': 'ff'}}, {'val': 55, 'c': {'name': 'ww'}, 'r': {'name1': 'ff'}}, {'val': 22, 'c': {'name': 'dd'}, 'r': {'name1': 'aa'}}]
#                                                                     ^ typo here

def flatten(my_dict):
    res = []
    for sub in my_dict:
        print(sub)
        dict_ = {}
        for k, v in sub.items():
            if isinstance(v, dict):
                for k_new, v_new in v.items():
                    dict_[k_new] = v_new
            else:
                dict_[k] = v
        res.append(dict_)
    return res

result = flatten(d)
print(result)  # [{'name': 'ss', 'name1': 'ff', 'val': 454}, {'name': 'ww', 'name1': 'ff', 'val': 55}, {'name': 'dd', 'name1': 'aa', 'val': 22}]

Upvotes: 1

Related Questions