Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a nested dictionary from a flattened dictionary

I have a flattened dictionary which I want to make into a nested one, of the form

flat = {'X_a_one': 10,         'X_a_two': 20,          'X_b_one': 10,         'X_b_two': 20,          'Y_a_one': 10,         'Y_a_two': 20,         'Y_b_one': 10,         'Y_b_two': 20} 

I want to convert it to the form

nested = {'X': {'a': {'one': 10,                       'two': 20},                  'b': {'one': 10,                       'two': 20}},            'Y': {'a': {'one': 10,                       'two': 20},                 'b': {'one': 10,                       'two': 20}}} 

The structure of the flat dictionary is such that there should not be any problems with ambiguities. I want it to work for dictionaries of arbitrary depth, but performance is not really an issue. I've seen lots of methods for flattening a nested dictionary, but basically none for nesting a flattened dictionary. The values stored in the dictionary are either scalars or strings, never iterables.

So far I have got something which can take the input

test_dict = {'X_a_one': '10',              'X_b_one': '10',              'X_c_one': '10'} 

to the output

test_out = {'X': {'a_one': '10',                    'b_one': '10',                    'c_one': '10'}} 

using the code

def nest_once(inp_dict):     out = {}     if isinstance(inp_dict, dict):         for key, val in inp_dict.items():             if '_' in key:                 head, tail = key.split('_', 1)                  if head not in out.keys():                     out[head] = {tail: val}                 else:                     out[head].update({tail: val})             else:                 out[key] = val     return out  test_out = nest_once(test_dict) 

But I'm having trouble working out how to make this into something which recursively creates all levels of the dictionary.

Any help would be appreciated!

(As for why I want to do this: I have a file whose structure is equivalent to a nested dict, and I want to store this file's contents in the attributes dictionary of a NetCDF file and retrieve it later. However NetCDF only allows you to put flat dictionaries as the attributes, so I want to unflatten the dictionary I previously stored in the NetCDF file.)

like image 491
ThomasNicholas Avatar asked May 30 '18 14:05

ThomasNicholas


People also ask

How do you nest a dictionary in a dictionary?

You can create a nested dictionary in Python by placing comma-separated dictionaries within curly braces {}. A Python nested dictionary allows you to store and access data using the key-value mapping structure within an existing dictionary.

How do you flatten nested dictionary?

Basically the same way you would flatten a nested list, you just have to do the extra work for iterating the dict by key/value, creating new keys for your new dictionary and creating the dictionary at final step. For Python >= 3.3, change the import to from collections.

How do you make a nested dictionary in Python?

Creating a Nested Dictionary In Python, a Nested dictionary can be created by placing the comma-separated dictionaries enclosed within braces.

What is flattened dictionary?

a : to make level or smooth. b : to knock down also : to defeat decisively. c : to make dull or uninspired —often used with out. d : to make lusterless flatten paint. e : to stabilize especially at a lower level.


1 Answers

Here is my take:

def nest_dict(flat):     result = {}     for k, v in flat.items():         _nest_dict_rec(k, v, result)     return result  def _nest_dict_rec(k, v, out):     k, *rest = k.split('_', 1)     if rest:         _nest_dict_rec(rest[0], v, out.setdefault(k, {}))     else:         out[k] = v  flat = {'X_a_one': 10,         'X_a_two': 20,          'X_b_one': 10,         'X_b_two': 20,          'Y_a_one': 10,         'Y_a_two': 20,         'Y_b_one': 10,         'Y_b_two': 20} nested = {'X': {'a': {'one': 10,                       'two': 20},                  'b': {'one': 10,                       'two': 20}},            'Y': {'a': {'one': 10,                       'two': 20},                 'b': {'one': 10,                       'two': 20}}} print(nest_dict(flat) == nested) # True 
like image 179
jdehesa Avatar answered Sep 19 '22 15:09

jdehesa