Iterate over nested dictionary

后端 未结 5 1877
孤城傲影
孤城傲影 2020-11-30 02:24

Is there an easy way of iterating over nested dictionary, which may consist of other objects like lists, tuples, then again dictionaries so that iteration covers all the ele

相关标签:
5条回答
  • 2020-11-30 03:13

    Iterating over a nested dictionary containing unexpected nested elements.

    Here is my solution :

    # d is the nested dictionary
    
    for item in d:
        if type(item) == list:
            print "Item is a list"
            for i in item: print i
        elif type(item) == dict:
            print "Item is a dict"
            for i in item: print i
        elif type(item) == tuple:
            print "Item is a tuple"
            for i in item: print i
        else:
            print "Item is not a list, neither a dict and not even a tuple"
            print item
    

    I think the above example is very general, you can mold it for your use case.

    0 讨论(0)
  • def recurse(d):
      if type(d)==type({}):
        for k in d:
          recurse(d[k])
      else:
        print d
    
    0 讨论(0)
  • 2020-11-30 03:17

    Here is another solution,

    #!/usr/bin/python
    
    d = {'key_1': 'value_1',
         'key_2': {'key_21': [(2100, 2101), (2110, 2111)],
               'key_22': ['l1', 'l2'],
               'key_23': {'key_231': 'v'},
               'key_24': {'key_241': 502,
                          'key_242': [(5, 0), (7, 0)],
                          'key_243': {'key_2431': [0, 0],
                                      'key_2432': 504,
                                      'key_2433': [(11451, 0), (11452, 0)]},
                          'key_244': {'key_2441': ['ll1', 'll2']}}}}
    
    def search_it(nested, target):
        found = []
        for key, value in nested.iteritems():
            if key == target:
                found.append(value)
            elif isinstance(value, dict):
                found.extend(search_it(value, target))
            elif isinstance(value, list):
                for item in value:
                    if isinstance(item, dict):
                        found.extend(search_it(item, target))
            else:
                if key == target:
                    found.append(value)
        return found
    
    keys = [ 'key_242', 'key_243', 'key_242', 'key_244', 'key_1' ]
    
    for key in keys:
        f = search_it(d, key)
        print 'Key: %s, value: %s' % (key, f[0])
    

    Output:

    Key: key_242, value: [(5, 0), (7, 0)]
    Key: key_243, value: {'key_2433': [(11451, 0), (11452, 0)], 'key_2432': 504, 'key_2431': 
     [0, 0]}
    Key: key_242, value: [(5, 0), (7, 0)]
    Key: key_244, value: {'key_2441': ['ll1', 'll2']}
    Key: key_1, value: value_1
    
    0 讨论(0)
  • 2020-11-30 03:22

    What about using a general-purpose wrapper generator, like the following:

    def recursive(coll):
        """Return a generator for all atomic values in coll and its subcollections.
        An atomic value is one that's not iterable as determined by iter."""
        try:
            k = iter(coll)
            for x in k:
                for y in recursive(x):
                    yield y
        except TypeError:
            yield coll
    
    
    def test():
        t = [[1,2,3], 4, 5, [6, [7, 8], 9]]
        for x in recursive(t):
            print x
    
    0 讨论(0)
  • 2020-11-30 03:24

    A generator version of Graddy's recurse() answer above that should not explode on strings, and also gives you the compound key (cookie crumb trail?) showing how you arrived at a certain value:

    def recurse(d, keys=()):
        if type(d) == dict:
             for k in d:
                for rv in recurse(d[k], keys + (k, )):
                    yield rv
        else:
            yield (keys, d)
    
    for compound_key, val in recurse(eg_dict):
        print '{}: {}'.format(compound_key, val)
    

    produces output (using the example dictionary provided in the question):

    ('key_1',): value_1
    ('key_2', 'key_21'): [(2100, 2101), (2110, 2111)]
    ('key_2', 'key_22'): ['l1', 'l2']
    ('key_2', 'key_23', 'key_231'): v
    ('key_2', 'key_24', 'key_241'): 502
    ('key_2', 'key_24', 'key_243', 'key_2433'): [(11451, 0), (11452, 0)]
    ('key_2', 'key_24', 'key_243', 'key_2432'): 504
    ('key_2', 'key_24', 'key_243', 'key_2431'): [0, 0]
    ('key_2', 'key_24', 'key_242'): [(5, 0), (7, 0)]
    ('key_2', 'key_24', 'key_244', 'key_2441'): ['ll1', 'll2']
    

    In Python 3 the second yield loop should be replaceable with yield from. This generator could be made more general by replacing the type(d) == dict test with isinstance(d, collections.Mapping), using the Mapping ABC from the collections module.

    0 讨论(0)
提交回复
热议问题