Brian Zheng
Brian Zheng

Reputation: 449

Python search for keys/values in nested dictionary

I have a nested dictionary like this

profile = {
    "Person":{
        "name":{
            "First_Name":["John"], 
            "Last_Name":['Doe']
        }
    }, 
    "Object":{
        "name":{
            "First_Name":['John'], 
            "Last_Name":['Doe']
        }
    }
}

I don't know how to write a piece of code to print the steps to find "First_Name" and "John" and identify whether it is a key or a value. There might also be several values that are the same in the nested dictionary and I want all of them. For example:

First_Name is a key and is located in profile['Person']['name']['First_Name']
John is a value and is located in profile['Person']['name']['First_Name']
First_Name is a key and is located in profile['Object']['name']['First_Name']
John is a value and is located in profile['Object']['name']['First_Name']

Upvotes: 3

Views: 1322

Answers (2)

hygull
hygull

Reputation: 8740

You can try like this.

Suggestion: Create a function and implement reusability (Functional approach) and that is a best way (you can use OOP approach as well). Here I have just tried to fulfil the need.

In case if you choose OOP later, you can a little look at https://stackoverflow.com/a/55671535/6615163 and try to get idea (If you are new to OOP otherwise it is okay).

Here, I have tried to add Last_Name (i.e. all the keys), if you only want First_Name then you can place a conditional statement inside inner (3rd) loop and stop skipping the addition to the list.

import json

profile = {
    "Person":{
        "name":{
            "First_Name":["John"], 
            "Last_Name":['Doe']
        }
    }, 
    "Object":{
        "name":{
            "First_Name":['John'], 
            "Last_Name":['Doe']
        }
    }
}

# START
messages = []
for key1 in profile:
    for key2 in profile[key1]:
        for key3 in profile[key1][key2]:
            message = "{0} is a {1} and is located in profile['{2}']['{3}']['{4}']"
            messages.append(message.format(key3, 'key', key1, key2, key3))
            messages.append(message.format(profile[key1][key2][key3][0], 'value', key1, key2, key3))

# --- Pretty print the list `messages` (indentation 4) ---
print(json.dumps(messages, indent=4))
# [
#     "First_Name is a key and is located in profile['Person']['name']['First_Name']",
#     "John is a value and is located in profile['Person']['name']['First_Name']",
#     "Last_Name is a key and is located in profile['Person']['name']['Last_Name']",
#     "Doe is a value and is located in profile['Person']['name']['Last_Name']",
#     "First_Name is a key and is located in profile['Object']['name']['First_Name']",
#     "John is a value and is located in profile['Object']['name']['First_Name']",
#     "Last_Name is a key and is located in profile['Object']['name']['Last_Name']",
#     "Doe is a value and is located in profile['Object']['name']['Last_Name']"
# ]


# --- As a string ---
print('\n'.join(messages))
# First_Name is a key and is located in profile['Person']['name']['First_Name']
# John is a value and is located in profile['Person']['name']['First_Name']
# Last_Name is a key and is located in profile['Person']['name']['Last_Name']
# Doe is a value and is located in profile['Person']['name']['Last_Name']
# First_Name is a key and is located in profile['Object']['name']['First_Name']
# John is a value and is located in profile['Object']['name']['First_Name']
# Last_Name is a key and is located in profile['Object']['name']['Last_Name']
# Doe is a value and is located in profile['Object']['name']['Last_Name']

Upvotes: 1

The question is a little vague but a solution like this may work. This solution will print your style of output for all values that are not nested dicts. If a value for the key is a dict type then the function will recurse till it finds values that are not nested to print.

def print_nested_dict(nested_dict, name, prior_keys=[]):
    for key, value in nested_dict.items():
        # current_key_path is a list of each key we used to get here
        current_key_path = prior_keys + [key]
        # Convert that key path to a string
        key_path_str = ''.join('[\'{}\']'.format(key) for key in current_key_path)

        # If the value is a dict then recurse
        if isinstance(value, dict):
            print_nested_dict(value, name, current_key_path)
        else:
            # Else lets print the key and value for this value
            print("{} is a key and is located in {}{}".format(key, name, key_path_str))
            print("{} is a value and is located in {}{}".format(value, name, key_path_str))

print_nested_dict(profile, "profile")

Output:

First_Name is a key and is located in profile['Person']['name']['First_Name']
['John'] is a value and is located in profile['Person']['name']['First_Name']
Last_Name is a key and is located in profile['Person']['name']['Last_Name']
['Doe'] is a value and is located in profile['Person']['name']['Last_Name']
First_Name is a key and is located in profile['Object']['name']['First_Name']
['John'] is a value and is located in profile['Object']['name']['First_Name']
Last_Name is a key and is located in profile['Object']['name']['Last_Name']
['Doe'] is a value and is located in profile['Object']['name']['Last_Name']

Upvotes: 1

Related Questions