Loop through all nested dictionary values?

前端 未结 12 1244
温柔的废话
温柔的废话 2020-11-22 09:16
for k, v in d.iteritems():
    if type(v) is dict:
        for t, c in v.iteritems():
            print \"{0} : {1}\".format(t, c)

I\'m trying to l

12条回答
  •  粉色の甜心
    2020-11-22 09:51

    There are potential problems if you write your own recursive implementation or the iterative equivalent with stack. See this example:

        dic = {}
        dic["key1"] = {}
        dic["key1"]["key1.1"] = "value1"
        dic["key2"]  = {}
        dic["key2"]["key2.1"] = "value2"
        dic["key2"]["key2.2"] = dic["key1"]
        dic["key2"]["key2.3"] = dic
    

    In the normal sense, nested dictionary will be a n-nary tree like data structure. But the definition doesn't exclude the possibility of a cross edge or even a back edge (thus no longer a tree). For instance, here key2.2 holds to the dictionary from key1, key2.3 points to the entire dictionary(back edge/cycle). When there is a back edge(cycle), the stack/recursion will run infinitely.

                              root<-------back edge
                            /      \           |
                         _key1   __key2__      |
                        /       /   \    \     |
                   |->key1.1 key2.1 key2.2 key2.3
                   |   /       |      |
                   | value1  value2   |
                   |                  | 
                  cross edge----------|
    

    If you print this dictionary with this implementation from Scharron

        def myprint(d):
          for k, v in d.items():
            if isinstance(v, dict):
              myprint(v)
            else:
              print "{0} : {1}".format(k, v)
    

    You would see this error:

        RuntimeError: maximum recursion depth exceeded while calling a Python object
    

    The same goes with the implementation from senderle.

    Similarly, you get an infinite loop with this implementation from Fred Foo:

        def myprint(d):
            stack = list(d.items())
            while stack:
                k, v = stack.pop()
                if isinstance(v, dict):
                    stack.extend(v.items())
                else:
                    print("%s: %s" % (k, v))
    

    However, Python actually detects cycles in nested dictionary:

        print dic
        {'key2': {'key2.1': 'value2', 'key2.3': {...}, 
           'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
    

    "{...}" is where a cycle is detected.

    As requested by Moondra this is a way to avoid cycles (DFS):

    def myprint(d): 
      stack = list(d.items()) 
      visited = set() 
      while stack: 
        k, v = stack.pop() 
        if isinstance(v, dict): 
          if k not in visited: 
            stack.extend(v.items()) 
          else: 
            print("%s: %s" % (k, v)) 
          visited.add(k)
    

提交回复
热议问题