How to search in a very nested dictionary based on a value and get all the main keys

Question:

I have a nested dictionary like this:

my_dict = {
        "אבד": {
        "קל": {
            "עבר": {
                "אני": "אבדתי",
                "אתה": "אבדת",
                "את": "אבדת",
                "הוא": "אבד",
                "היא": "אבדה",
                "אנחנו": "אבדנו",
                "אתם": "אבדתם",
                "אתן": "אבדתן",
                "הם/הן": "אבדו"
            },
            "עתיד": {
                "אני": "אובד",
                "אתה": "תאבד",
                "את": "תאבדי",
                "הוא": "יאבד",
                "היא": "תאבד",
                "אנחנו": "נאבד",
                "אתם/אתן": "תאבדו",
                "אתן": "תאבדנה",
                "הם/הן": "יאבדו",
                "הן": "תאבדנה"
            },
            "הווה": {
                "יחיד": "אובד, אבד",
                "יחידה": "אובדת, אבדה",
                "רבים": "אובדים, אבדים",
                "רבות": "אובדות, אבדות"
            },
            "ציווי": {
                "אתה": "אבוד",
                "את": "אבדי",
                "אתם/אתן": "אבדו",
                "אתן": "אבודנה"
            },
            "שם הפועל": "לאבוד"
        },
        "נפעל": {
            "עבר": {
                "אני": "נאבדתי",
                "אתה": "נאבדת",
                "את": "נאבדת",
                "הוא": "נאבד",
                "היא": "נאבדה",
                "אנחנו": "נאבדנו",
                "אתם": "נאבדתם",
                "אתן": "נאבדתן",
                "הם/הן": "נאבדו"
            },
            "עתיד": {
                "אני": "איאבד",
                "אתה": "תיאבד",
                "את": "תיאבדי",
                "הוא": "ייאבד",
                "היא": "תיאבד",
                "אנחנו": "ניאבד",
                "אתם/אתן": "תיאבדו",
                "אתן": "תיאבדנה",
                "הם/הן": "ייאבדו",
                "הן": "תיאבדנה"
            },
            "הווה": {
                "יחיד": "נאבד",
                "יחידה": "נאבדת",
                "רבים": "נאבדים",
                "רבות": "נאבדות"
            },
            "ציווי": {
                "אתה": "היאבד",
                "את": "היאבדי",
                "אתם/אתן": "היאבדו",
                "אתן": "היאבדנה"
            },
            "שם הפועל": "להיאבד"
        },
        "פיעל": {
            "עבר": {
                "אני": "איבדתי",
                "אתה": "איבדת",
                "את": "איבדת",
                "הוא": "איבד",
                "היא": "איבדה",
                "אנחנו": "איבדנו",
                "אתם": "איבדתם",
                "אתן": "איבדתן",
                "הם/הן": "איבדו"
            },
            "עתיד": {
                "אני": "אאבד",
                "אתה": "תאבד",
                "את": "תאבדי",
                "הוא": "יאבד",
                "היא": "תאבד",
                "אנחנו": "נאבד",
                "אתם/אתן": "תאבדו",
                "אתן": "תאבדנה",
                "הם/הן": "יאבדו",
                "הן": "תאבדנה"
            },
            "הווה": {
                "יחיד": "מאבד",
                "יחידה": "מאבדת",
                "רבים": "מאבדים",
                "רבות": "מאבדות"
            },
            "ציווי": {
                "אתה": "אבד",
                "את": "אבדי",
                "אתם/אתן": "אבדו",
                "אתן": "אבדנה"
            },
            "שם הפועל": "לאבד"
        },
        "הפעיל": {
            "עבר": {
                "אני": "האבדתי",
                "אתה": "האבדת",
                "את": "האבדת",
                "הוא": "האביד",
                "היא": "האבידה",
                "אנחנו": "האבדנו",
                "אתם": "האבדתם",
                "אתן": "האבדתן",
                "הם/הן": "האבידו"
            },
            "עתיד": {
                "אני": "אאביד",
                "אתה": "תאביד",
                "את": "תאבידי",
                "הוא": "יאביד",
                "היא": "תאביד",
                "אנחנו": "נאביד",
                "אתם/אתן": "תאבידו",
                "אתן": "תאבדנה",
                "הם/הן": "יאבידו",
                "הן": "תאבדנה"
            },
            "הווה": {
                "יחיד": "מאביד",
                "יחידה": "מאבידה",
                "רבים": "מאבידים",
                "רבות": "מאבידות"
            },
            "ציווי": {
                "אתה": "האבד",
                "את": "האבידי",
                "אתם/אתן": "האבידו",
                "אתן": "האבדנה"
            },
            "שם הפועל": "להאביד"
        },
        "הופעל": {
            "עבר": {
                "אני": "הואבדתי",
                "אתה": "הואבדת",
                "את": "הואבדת",
                "הוא": "הואבד",
                "היא": "הואבדה",
                "אנחנו": "הואבדנו",
                "אתם": "הואבדתם",
                "אתן": "הואבדתן",
                "הם/הן": "הואבדו"
            },
            "עתיד": {
                "אני": "אואבד",
                "אתה": "תואבד",
                "את": "תואבדי",
                "הוא": "יואבד",
                "היא": "תואבד",
                "אנחנו": "נואבד",
                "אתם/אתן": "תואבדו",
                "אתן": "תואבדנה",
                "הם/הן": "יואבדו",
                "הן": "תואבדנה"
            },
            "הווה": {
                "יחיד": "מואבד",
                "יחידה": "מואבדת",
                "רבים": "מואבדים",
                "רבות": "מואבדות"
            }
        },
        "התפעל": {
            "עבר": {
                "אני": "התאבדתי",
                "אתה": "התאבדת",
                "את": "התאבדת",
                "הוא": "התאבד",
                "היא": "התאבדה",
                "אנחנו": "התאבדנו",
                "אתם": "התאבדתם",
                "אתן": "התאבדתן",
                "הם/הן": "התאבדו"
            },
            "עתיד": {
                "אני": "אתאבד",
                "אתה": "תתאבד",
                "את": "תתאבדי",
                "הוא": "יתאבד",
                "היא": "תתאבד",
                "אנחנו": "נתאבד",
                "אתם/אתן": "תתאבדו",
                "אתן": "תתאבדנה",
                "הם/הן": "יתאבדו",
                "הן": "תתאבדנה"
            },
            "הווה": {
                "יחיד": "מתאבד",
                "יחידה": "מתאבדת",
                "רבים": "מתאבדים",
                "רבות": "מתאבדות"
            },
            "ציווי": {
                "אתה": "התאבד",
                "את": "התאבדי",
                "אתם/אתן": "התאבדו",
                "אתן": "התאבדנה"
            },
            "שם הפועל": "להתאבד"
        }
    }
}

I what I want is to search keys based on value inputted by a user. so for example, if a user input "האבדנו" then the result shall be getting the main three keys that leads to this value as follow:
direct key of the value the user typed id "אנחנו"
The second direct key is "עבר"
the third direct key is "הפעיל"

For some reasons I don’t know why the code shows the keys on the right and values on the left when I pasted the dictionary.

I tried to use yield and but I success in getting only the first direct key, here is my code:

def recursive_items(dictionary):
    for key, value in dictionary.items():
        if type(value) is dict:
            yield (key, value)
            yield from recursive_items(value)
        else:
            yield (key, value)
            
for key, val in recursive_items(my_dict):
    if val == "האבדנו":
        print(key)
# output is אנחנו which is the direct key

Is it possible to search backwards in a very nested dictionary?

Thank you

I also tried with:

def map_keys(dic, input):
    keys = []
    for key, value in dic.items():
        for k1, v1 in value.items():
            for k2, v2 in v1.items():
                if type(v2) is dict:
                    for k3, v3 in v2.items():
                        if input == v3:
                            keys.append(k3)
                            keys.append(k2)
                            keys.append(k1)
                            keys.append(key)
                else:
                    if input == v2:
                        keys.append(k2)
                        keys.append(k1)
                        keys.append(key)
    return keys

Update:
the checked answer does work for me. thanks for Andrej

Asked By: Bumblebee

||

Answers:

Try:

def search(dct, word, current_path=None):
    if current_path is None:
        current_path = []

    for k, v in dct.items():
        if v == word:
            yield current_path
        elif isinstance(v, dict):
            yield from search(v, word, current_path + [k])


for path in search(my_dict, "האבדנו"):
    print(path)

Prints:

['אבד', 'הפעיל', 'עבר']
Answered By: Andrej Kesely
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.