Home > Software engineering >  point specific key and value from highly nested dictionary
point specific key and value from highly nested dictionary

Time:01-06

I believe there must be a way to point specific key from nested dict, not in the traditional ways.

imagine dictionary like this.

dict1 = { 'level1': "value",
         'unexpectable': { 'maybe': { 'onemotime': {'name': 'John'} } } }

dict2 = { 'level1': "value", 'name': 'Steve'} 

dict3 = { 'find': { 'what': { 'you': { 'want': { 'in': { 'this': { 'maze': { 'I': { 'made': { 'for': { 'you': { 'which': { 'is in': { 'fact that': { 'was just': { 'bully your': { 'searching': { 'for': { 'the name': { 'even tho': { 'in fact': { 'actually': { 'there': { 'is': { 'in reality': { 'only': { 'one': { 'key': { 'named': { 'name': 'Michael' } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }

in this case, if we want to point 'name' key to get 'John' and 'Steve' and the 'Michael', you should code differently against dict1 and dict2 and dict3

and the traditional way to point the key buried in nested dictionary that I know is this.

print(dict1['unexpectable']['maybe']['onemotime']['name'])

and if you don't want your code to break because of empty value of dict, you may want to use get() function.

and I'm curious that if I want to get 'name' of dict1 safely with get(), should I code like this?

print(dict1.get('unexpectable', '').get('maybe', '').get('onemotime', '').get('name', ''))

in fact, i've got error when run those get().get().get().get() thing.

And please consider if you have to print() 'name' from that horrible dict3 even it has actually only one key.

and, imagine the case you extract 'name' from unknown dict4 which you cannot imagine what nesting structure the dict4 would have.

I believe that python must have a way to deal with this.

I searched on the internet about this problem, but the solutions seems really really difficult.

I just wanted simple solution.

the solution without pointing every keys on the every level. like just pointing that last level key, the most important key. like, print(dict1.lastlevel('name')) --> 'John'

like, no matter what structure of nesting levels they have, no matter how many duplicates they have, even if they omitted nested key in the middle of nested dict so that dict17 has one less level of dict16, you could get what you want, the last level value of the last level key.

So Conclusion.

I want to know if there is a simple solution like

print(dict.lastlevel('name'))

without creating custom function.

I want to know if there is solution like above from the default python methods, syntax, function, logic or concept.

The solution like above can be applied to dict1, dict2, dict3, to whatever dict would come.

CodePudding user response:

There is no build-in method to accomplish what you are asking for. However, you can use a recursive function to dig through a nested dictionary. The function checks if the desired key is in the dictionary and returns the value if it is. Otherwise it iterates over the dict's values for other dictionaries and scans their keys as well, repeating until it reaches the bottom.

dict1 = { 'level1': "value",
         'unexpectable': { 'maybe': { 'onemotime': {'name': 'John'} } } }
dict2 = { 'level1': "value", 'name': 'Steve'} 
dict3 = { 'find': { 'what': { 'you': { 'want': { 'in': { 'this': { 'maze': { 'I': {
          'made': { 'for': { 'you': { 'which': { 'is in': { 'fact that': { 
          'was just': { 'bully your': { 'searching': { 'for': { 'the name': { 
          'even tho': { 'in fact': { 'actually': { 'there': { 'is': { 'in reality': {
          'only': { 'one': { 'key': { 'named': { 'name': 'Michael' 
         } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }


def get_nested_dict_key(d, key):
    if key in d:
        return d[key]
    else:
        for item in d.values():
            if not isinstance(item, dict):
                continue
            return get_nested_dict_key(item, key)

          
print(get_nested_dict_key(dict1, 'name'))
print(get_nested_dict_key(dict2, 'name'))
print(get_nested_dict_key(dict3, 'name'))
# prints:
# John
# Steve
# Michael


CodePudding user response:

You can make simple recursive generator function which yields value of every particular key:

def get_nested_key(source, key):
    if isinstance(source, dict):
        key_value = source.get(key)
        if key_value:
            yield key_value
        for value in source.values():
            yield from get_nested_key(value, key)
    elif isinstance(source, (list, tuple)):
        for value in source:
            yield from get_nested_key(value, key)

Usage:

dictionaries = [
    {'level1': 'value', 'unexpectable': {'maybe': {'onemotime': {'name': 'John'}}}},
    {'level1': 'value', 'name': 'Steve'},
    {'find': {'what': {'you': {'want': {'in': {'this': {'maze': {'I': {'made': {'for': {'you': {'which': {'is in': {'fact that': {'was just': {'bully your': {'searching': {'for': {'the name': {'even tho': {'in fact': {'actually': {'there': {'is': {'in reality': {'only': {'one': {'key': {'named': {'name': 'Michael'}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
    {'level1': 'value', 'unexpectable': {'name': 'Alex', 'maybe': {'onemotime': {'name': 'John'}}}},
    {}
]

for d in dictionaries:
    print(*get_nested_key(d, 'name'), sep=', ')

Output:

John
Steve
Michael
Alex, John

  • Related