Recursively iterate through a nested dict and return value of the first matching key

青春壹個敷衍的年華 提交于 2020-06-16 02:55:14

问题


I have a deeply nested dict and need to iterate through it and return the value corresponding to the key argument, second argument of my function.

For example, with

tree = {"a": 12, "g":{ "b": 2, "c": 4}, "d":5}

tree_traverse(tree, "d") should return 5

Here is my code:

def tree_traverse(tree, key):
    for k,v  in tree.items():
        if isinstance(v, dict):
            tree_traverse(v, key)

        elif k == key:
            return v

The problem I have is that this function returns None if it doesnt find the matching key once it's done iterating through the deepest nested dict. I don't want it to return anything before the matching key is found.

I didn't find a solution in another thread, most of them use print statements and don't return anything so I guess it avoids this issue.


回答1:


You have to check whether the recursive call actually found something so you can continue the loop. E.g. try the following:

def tree_traverse(tree, key):
    for k, v  in tree.items():
        if k == key:
            return v
        elif isinstance(v, dict):
            found = tree_traverse(v, key) 
            if found is not None:  # check if recursive call found it
                return found



回答2:


Here we instantiate an object when the function is created, that all executions of the function will share, called _marker. We return this object if we don't find the key. (You could also use None here, but None is frequently a meaningful value.)

def tree_traverse(tree, key, *, _marker=object()):
    for k,v  in tree.items():
        if isinstance(v, dict):
            res = tree_traverse(v, key, _marker=_marker)
            if res is not _marker:
                return res
        elif k == key:
            return v
    return _marker

def find(tree, key):
    _marker = object()
    res = tree_traverse(tree, key, _marker=_marker)
    if res is _marker:
        raise KeyError("Key {} not found".format(key))
    return res

I use tree_traverse as a helper function because we want different behaviour at the outermost layer of our recursion (throw an error) than we want inside (return a _marker object)



来源:https://stackoverflow.com/questions/52260624/recursively-iterate-through-a-nested-dict-and-return-value-of-the-first-matching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!