简体   繁体   中英

Flattening nested dictionary with possible list of dictionaries in python

I have a nested (dictionaries) and (list of dictionaries) - parentheses for clarity - like the following:

{"k": 
  {"hello": "bye",
   "hi": [{"a": "b", "c": "d"}, {"q": "I", "o": "p"}]
  }
}

And I want to flatten it into a path like the following:

"k/hello/bye/hi/a/b/c/d/q/I/o/p"

How can this be done? There may be more layers of dictionaries (even within the ones in a list), so I need a very scalable solution.

Thanks, Jack

Recursive Solution

Recursion hardly ever works first run, guess I was lucky:

def traverse(struct):
    if isinstance(struct, dict):
        return '/'.join(k+'/'+traverse(v) for k,v in struct.items())
    elif isinstance(struct, list):
        return '/'.join(traverse(v) for v in struct)
    else:
        return struct

which gives:

'k/hello/bye/hi/a/b/c/d/q/I/o/p'

why?

Each call to the traverse function takes a struct argument which can be either a dictionary, list, or string.

If it is a dictionary, we join together all the values followed by the result of traversing the corresponding keys. We then return this string.

Similarly, if it a list, we join together the outputs of traversing all the elements and return the result.

Finally, if the struct argument is just a string, we return it to our parent.

In every case, each function is unaware of wear it is in the stack of calls, it just knows what its struct argument was and returns the correct response for that , argument.

This is what is so cool about recursion, you only need to consider one case, and as long as you write it correctly and pass the right things from parent to child, the result just emerges through cooperation.


NB As @DanielMeseko notes in the comments, dictionaries aren't ordered so, for instance, the hello an hi parts of the final string could "switch places" (along with their children trees).


update

To make the dictionaries sorted by the alphabetical position of the keys, we just need to use the sorted() function on the result from struct.items() .

That is to stay: replace struct.items() in the above code with:

sorted(struct.items())

Which will sort alphabetically be default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM