Search code examples
jsonpython-3.xdictionaryflatten

Flatten nested Python dictionary


I've seen quite a lot of answers on flattening dictionaries here but couldn't really apply any of them to my case. I have an example of the structure of the dictionary below and the output that I think would be ideal but not necessary. Anything to flatten it in a way that points to the value instead of the key would be great.

(most of the answers I found here were always using the key and that wouldn't be very helpful in this situation)

    b = [
          {'name': 'Level A',
           'children': [
               {'name': 'Level B',
                'children': [
                    {'name': 'Level C'},
                    {'name': 'Level D'},
                    {'name': 'Level E',
                     'children': [
                         {'name': 'Level Z'}
                     ]}
                ]
                },
               {'name': 'Level F',
                'children': [
                    {'name': 'Level G'}
                ]}
           ]
           },
          {'name': 'Level M',
           'children': [{'name': 'Level N'},
                        {'name': 'Level Y'}
                        ]
           }
      ]

Wanted output:

l = ['Level A-Level B-Level C',
     'Level A-Level B-Level D',
     'Level A-Level B-Level E-Level Z',
     'Level A-Level F-Level G',
     'Level M-Level N',
     'Level M-Level Y']

Thank you all in advance!


Solution

  • Recursion + yield makes short work of this.

    def flatten(b):
        for d in b:
            if 'children' in d:
                for child in flatten(d['children']):
                    yield d['name'] + '-' + child
            else:
                yield d['name']
    
    result = [*flatten(b)]
    

    result contains

    ['Level A-Level B-Level C',
     'Level A-Level B-Level D',
     'Level A-Level B-Level E-Level Z',
     'Level A-Level F-Level G',
     'Level M-Level N',
     'Level M-Level Y']
    

    Note that the last two lines are different than your desired output, but I assume that's because you made an error. (Level M is not a child of Level A. It exists on the same level.)