diff --git a/benedict/dicts/__init__.py b/benedict/dicts/__init__.py index 6373619..0e06299 100644 --- a/benedict/dicts/__init__.py +++ b/benedict/dicts/__init__.py @@ -157,6 +157,13 @@ class benedict(IODict, KeypathDict, ParseDict): """ dict_util.traverse(self, callback) + def unflatten(self, separator='_'): + """ + Return a new unflattened dict using the given separator + to split dict keys to nested keypaths. + """ + return dict_util.unflatten(self, separator) + def unique(self): """ Remove duplicated values from the current dict instance. diff --git a/benedict/utils/dict_util.py b/benedict/utils/dict_util.py index 58cfa7e..be2a852 100644 --- a/benedict/utils/dict_util.py +++ b/benedict/utils/dict_util.py @@ -214,6 +214,22 @@ def traverse(d, callback): traverse(value, callback) +def unflatten(d, separator='_'): + new_dict = d.copy() + new_dict.clear() + new_dict_cursor = new_dict + keys = list(d.keys()) + for key in keys: + value = d.get(key, None) + new_value = unflatten(value, separator=separator) if isinstance( + value, dict) else value + new_keys = key.split(separator) if separator in key else [key] + new_parent, new_key, _ = resolve( + new_dict, new_keys, create_intermediates=True) + new_parent[new_key] = new_value + return new_dict + + def unique(d): values = [] keys = list(d.keys()) diff --git a/tests/test_benedict.py b/tests/test_benedict.py index 3322f52..2f1fc3c 100644 --- a/tests/test_benedict.py +++ b/tests/test_benedict.py @@ -1542,6 +1542,30 @@ b: } self.assertEqual(b, r) + def test_unflatten(self): + d = { + 'device_os': 'Windows', + 'device_lang': 'en-US', + 'device_code': 43, + 'browser_name': 'Chrome', + 'browser_layout': 'Webkit', + } + b = benedict(d) + u = b.unflatten() + r = { + 'device': { + 'os': 'Windows', + 'lang': 'en-US', + 'code': 43, + }, + 'browser': { + 'name': 'Chrome', + 'layout': 'Webkit', + }, + } + self.assertEqual(u, r) + self.assertEqual(u.flatten(), b) + def test_unique(self): d = { 'a': {