Search code examples
pythonnested-loops

Finding key in a Nested dictionary


I'm trying to find a key inside a nested dictionary:

mydict = {
    ('Geography', 1): {},
    ('Languages', 2): {
        ('English', 3): {
            ('Grammar', 6): {
                ('new', 10):{},
                ('old', 11): {}
            }
        },
        ('Spanish', 4): {},
        ('French', 5):  {
            ('Grammar', 7): {}
        },
        ('Dutch', 8): {
            ('Grammar', 9): {
                ('new', 12):{}
            }
        }
    }
}

So I loop inside the dictionary to find the key ('Grammar', 9) for example:

def _loop(topic, topics_dict):
    if (topic[0], topic[1]) in topics_dict.keys():
        return topics_dict[(topic[0], topic[1])]
    else:
        for k, v in topics_dict.items():
            if v != {}:
                return _loop(topic, v)

topic = ('Grammar', 9)
trim_mydict = _loop(topic, mydict)
print(trim_mydict)

But, in fact, it returns None instead of {('new', 12):{}}

I've checked this thread (Finding a key recursively in a dictionary) but I seem to be doing the exact same thing...


Solution

  • When you have return without a condition in the loop there it only returns the first result, even if it's None. I added a check like this:

    mydict = {
        ('Geography', 1): {},
        ('Languages', 2): {
            ('English', 3): {
                ('Grammar', 6): {
                    ('new', 10):{},
                    ('old', 11): {}
                }
            },
            ('Spanish', 4): {},
            ('French', 5):  {
                ('Grammar', 7): {}
            },
            ('Dutch', 8): {
                ('Grammar', 9): {
                    ('new', 10):{}
                }
            }
        }
    }
    
    
    def _loop(topic, topics_dict):
        if (topic[0], topic[1]) in topics_dict.keys():
            return topics_dict[(topic[0], topic[1])]
        else:
            for k, v in topics_dict.items():
                if v != {}:
                    if (result := _loop(topic, v)) is not None:
                        return result
    
    topic = ('Grammar', 9)
    trim_mydict = _loop(topic, mydict)
    print(trim_mydict)
    
    >>> {('new', 10): {}}