Added nest utility method.
This commit is contained in:
parent
78c20ca2ce
commit
46e55cf1c9
|
@ -13,6 +13,7 @@ from benedict.core.keylists import keylists
|
|||
from benedict.core.keypaths import keypaths
|
||||
from benedict.core.merge import merge
|
||||
from benedict.core.move import move
|
||||
from benedict.core.nest import nest
|
||||
from benedict.core.remove import remove
|
||||
from benedict.core.rename import rename
|
||||
from benedict.core.search import search
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from benedict.core.groupby import groupby
|
||||
|
||||
|
||||
def _nest_items(nested_items, item, id_key, children_key):
|
||||
children_items = nested_items.pop(item[id_key], [])
|
||||
item[children_key] = children_items
|
||||
for child_item in children_items:
|
||||
_nest_items(nested_items, child_item, id_key, children_key)
|
||||
|
||||
|
||||
def nest(items, id_key, parent_id_key, children_key):
|
||||
if any([id_key == parent_id_key,
|
||||
id_key == children_key,
|
||||
parent_id_key == children_key]):
|
||||
raise ValueError('keys should be different.')
|
||||
nested_items = groupby(items, parent_id_key)
|
||||
root_items = nested_items.get(None, [])
|
||||
for item in root_items:
|
||||
_nest_items(nested_items, item, id_key, children_key)
|
||||
return nested_items.get(None)
|
|
@ -12,6 +12,7 @@ from benedict.core import items_sorted_by_values as _items_sorted_by_values
|
|||
from benedict.core import keypaths as _keypaths
|
||||
from benedict.core import merge as _merge
|
||||
from benedict.core import move as _move
|
||||
from benedict.core import nest as _nest
|
||||
from benedict.core import remove as _remove
|
||||
from benedict.core import rename as _rename
|
||||
from benedict.core import search as _search
|
||||
|
@ -141,6 +142,13 @@ class benedict(IODict, KeypathDict, ParseDict):
|
|||
"""
|
||||
_move(self, key_src, key_dest)
|
||||
|
||||
def nest(self, key, id_key='id', parent_id_key='parent_id', children_key='children'):
|
||||
"""
|
||||
Nest a list of dicts at the given key and return a new nested list
|
||||
using the specified keys to establish the correct items hierarchy.
|
||||
"""
|
||||
return _nest(self[key], id_key, parent_id_key, children_key)
|
||||
|
||||
def remove(self, keys, *args):
|
||||
"""
|
||||
Remove multiple keys from the current dict instance.
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from benedict.core import clone as _clone
|
||||
from benedict.core import nest as _nest
|
||||
|
||||
import unittest
|
||||
|
||||
|
||||
class nest_test_case(unittest.TestCase):
|
||||
|
||||
def test_nest(self):
|
||||
l = [
|
||||
{'id':1, 'parent_id':None, 'name':'John'},
|
||||
{'id':2, 'parent_id':1, 'name':'Frank'},
|
||||
{'id':3, 'parent_id':2, 'name':'Tony'},
|
||||
{'id':4, 'parent_id':3, 'name':'Jimmy'},
|
||||
{'id':5, 'parent_id':1, 'name':'Sam'},
|
||||
{'id':6, 'parent_id':3, 'name':'Charles'},
|
||||
{'id':7, 'parent_id':2, 'name':'Bob'},
|
||||
{'id':8, 'parent_id':3, 'name':'Paul'},
|
||||
{'id':9, 'parent_id':None, 'name':'Michael'},
|
||||
]
|
||||
l_clone = _clone(l)
|
||||
n = _nest(l, 'id', 'parent_id', 'children')
|
||||
r = [
|
||||
{'id':1, 'parent_id':None, 'name':'John', 'children':[
|
||||
{'id':2, 'parent_id':1, 'name':'Frank', 'children':[
|
||||
{'id':3, 'parent_id':2, 'name':'Tony', 'children':[
|
||||
{'id':4, 'parent_id':3, 'name':'Jimmy', 'children':[], },
|
||||
{'id':6, 'parent_id':3, 'name':'Charles', 'children':[], },
|
||||
{'id':8, 'parent_id':3, 'name':'Paul', 'children':[], },
|
||||
], },
|
||||
{'id':7, 'parent_id':2, 'name':'Bob', 'children':[], },
|
||||
], },
|
||||
{'id':5, 'parent_id':1, 'name':'Sam', 'children':[], },
|
||||
]},
|
||||
{'id':9, 'parent_id':None, 'name':'Michael', 'children':[], },
|
||||
]
|
||||
self.assertEqual(l, l_clone)
|
||||
self.assertEqual(n, r)
|
||||
|
||||
def test_nest_with_wrong_keys(self):
|
||||
l = [
|
||||
{'id':1, 'parent_id':None, 'name':'John'},
|
||||
{'id':2, 'parent_id':1, 'name':'Frank'},
|
||||
{'id':3, 'parent_id':2, 'name':'Tony'},
|
||||
{'id':4, 'parent_id':3, 'name':'Jimmy'},
|
||||
{'id':5, 'parent_id':1, 'name':'Sam'},
|
||||
{'id':6, 'parent_id':3, 'name':'Charles'},
|
||||
{'id':7, 'parent_id':2, 'name':'Bob'},
|
||||
{'id':8, 'parent_id':3, 'name':'Paul'},
|
||||
{'id':9, 'parent_id':None, 'name':'Michael'},
|
||||
]
|
||||
with self.assertRaises(ValueError):
|
||||
n = _nest(l, 'id', 'id', 'children')
|
||||
with self.assertRaises(ValueError):
|
||||
n = _nest(l, 'id', 'parent_id', 'id')
|
||||
with self.assertRaises(ValueError):
|
||||
n = _nest(l, 'id', 'parent_id', 'parent_id')
|
||||
|
||||
def test_nest_with_wrong_input(self):
|
||||
l = {'id':1, 'parent_id':None, 'name':'John'}
|
||||
with self.assertRaises(ValueError):
|
||||
d = _nest(l, 'id', 'parent_id', 'children')
|
||||
l = [
|
||||
[{'id':1, 'parent_id':None, 'name':'John'},],
|
||||
[{'id':2, 'parent_id':1, 'name':'Frank'},],
|
||||
]
|
||||
with self.assertRaises(ValueError):
|
||||
d = _nest(l, 'id', 'parent_id', 'children')
|
Loading…
Reference in New Issue