Home > Enterprise >  How to loop through all nested dictionary to give all the parent key concatenated and its value
How to loop through all nested dictionary to give all the parent key concatenated and its value

Time:12-21

dictionary={' items': { 'heading': 'Maps','description':'Maps123','imagepath':/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

I want the output in the format:

items/heading: Maps

items/description: Maps123

items/image_path: /music/images/v2/web_api-music.png

items/config/config1: abcd

items/config/config2: hello

db/username: xyz

db/password: xyz

version: v1

CodePudding user response:

The answer of script0 results in an output that starts with a forward slash (/). I modified script0's code a little:

def flatten(x, parent=''):
    for key in x.keys():
        if isinstance(x[key], dict) and parent == '': flatten(x[key], key)
        elif isinstance(x[key], dict) and parent != '': flatten(x[key], f"{parent}/{key}")
        elif not isinstance(x[key], dict) and parent == '': print(f"{key}: {x[key]}")
        else: print(f"{parent}/{key}: {x[key]}")

dictionary= {'items': { 'heading': 'Maps','description':'Maps123','imagepath':'/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

flatten(dictionary)

Output (without the leading /):

items/heading: Maps
items/description: Maps123
items/imagepath: /music/images/
items/config/config1: 12
items/config/config2: 123
db/username: xyz
db/password: xyz
version: v1

Please note that you could also create a new dictionary with the left-hand side of the output as the keys and the right-hand side as the values.

For example:

new_dict = {}

def flatten(x, parent=''):
    for key in x.keys():
        if isinstance(x[key], dict) and parent == '': flatten(x[key], key)
        elif isinstance(x[key], dict) and parent != '': flatten(x[key], f"{parent}/{key}")
        elif not isinstance(x[key], dict) and parent == '': new_dict[key] = x[key]
        else: new_dict[f"{parent}/{key}"] = x[key]

dictionary= {'items': { 'heading': 'Maps','description':'Maps123','imagepath':'/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

flatten(dictionary)
print(new_dict)

Output:

{'items/heading': 'Maps', 'items/description': 'Maps123', 'items/imagepath': '/music/images/', 'items/config/config1': 12, 'items/config/config2': 123, 'db/username': 'xyz', 'db/password': 'xyz', 'version': 'v1'}

CodePudding user response:

Check it :

def flatten(x, parent=''):
    for key in list(x.keys()):
        if( type(x[key]) is dict ):
            flatten(x[key], parent '/' str(key))
        else:
            print(parent '/' str(key) ': '   str(x[key]))

dictionary={'items': { 'heading': 'Maps','description':'Maps123','imagepath':'/music/images/','config':{'config1':12,'config2':123}},'db':{'username':'xyz','password':'xyz'},'version':'v1'}

flatten(dictionary)

CodePudding user response:

A recursive function is best for this. It only needs to check the type of the parameter and pass down a path of keys:

def paths(D,P=[]):
    if isinstance(D,dict):
        return {p:v for k,d in D.items() for p,v in paths(d,P [k]).items()} 
    else:
        return {"/".join(P):D}

Output:

print(paths(dictionary))

{'items/heading': 'Maps',
 'items/description': 'Maps123',
 'items/imagepath': '/music/images/',
 'items/config/config1': 12,
 'items/config/config2': 123,
 'db/username': 'xyz',
 'db/password': 'xyz',
 'version': 'v1'}

To make this a bit more efficient, you could make the function a generator and only create a dictionary from the extracted tuples at the end.

def paths(D,P=[]):
    if isinstance(D,dict):
        yield from ((p,v) for k,d in D.items() for p,v in paths(d,P [k])) 
    else:
        yield ("/".join(P),D)
                        
dictionary = dict(paths(dictionary))
  • Related