Python 如何从具有父项id的dict创建具有子项的dict
如何从这条格言中获得:Python 如何从具有父项id的dict创建具有子项的dict,python,dictionary,parent-child,Python,Dictionary,Parent Child,如何从这条格言中获得: cats = [ {'parent_id': False, 'id': 1, 'title': u'All'}, {'parent_id': False, 'id': 2, 'title': u'Toys'}, {'parent_id': 2, 'id': 3, 'title': u'Toypads'}, {'parent_id': 3, 'id': 4, 'title': u'Green'}, ] 像这样的 cats =
cats = [
{'parent_id': False, 'id': 1, 'title': u'All'},
{'parent_id': False, 'id': 2, 'title': u'Toys'},
{'parent_id': 2, 'id': 3, 'title': u'Toypads'},
{'parent_id': 3, 'id': 4, 'title': u'Green'},
]
像这样的
cats = [
{'parent_id': False, 'id': 1, 'title': u'All'},
{'parent_id': False,
'children': [{'parent_id': 2,
'children': [{'parent_id': 3, 'id': 4,
'title': u'Green'}],
'id': 3, 'title': u'Toypads'},
[{'parent_id': 3, 'id': 4, 'title': u'Green'}]],
'id': 2, 'title': u'Toys'}
]
我需要它在Jinja2中构建一个菜单\子菜单。
我写了一个非常糟糕的代码。这将是一个更优雅的解决方案
q = dict(zip([i['id'] for i in cats], cats))
from collections import defaultdict
parent_map = defaultdict(list)
for item in q.itervalues():
parent_map[item['parent_id']].append(item['id'])
def tree_level(parent):
for item in parent_map[parent]:
yield q[item]
sub_items = list(tree_level(item))
if sub_items:
for ca in cats:
if ca['id'] == item:
cats[cats.index(ca)]['children'] = sub_items
for s_i in sub_items:
try:
for ca_del_child in cats:
if ca_del_child['id'] == s_i['id']:
del cats[cats.index(ca_del_child)]
except:
pass
yield sub_items
for i in list(tree_level(False)):
pass
可按如下方式进行:
# Step 1: index all categories by id and add an element 'children'
nodes = {}
for cat in cats:
nodes[cat['id']] = cat
cat['children'] = []
# Step 2: For each category, add it to the parent's children
for index, cat in nodes.items():
if cat['parent_id']:
nodes[cat['parent_id']]['children'].append(cat)
# Step 3: Keep only those that do not have a parent
cats = [c for c in nodes.values() if not c['parent_id']]
请注意,每个节点都有一个名为'children'
的属性,该属性可以是空列表,也可以是包含一个或多个节点的列表。如果您不想要空的子列表
,只需在步骤2和步骤2之间从节点
中的每个类别中删除它们即可
还请注意,上面假设实际存在具有给定父id的节点。最后,请注意,当id为零的节点存在时,
如果不是c['parent_id']
也将是真的,因此如果出现这种情况,您需要记住。可以按如下方式执行:
# Step 1: index all categories by id and add an element 'children'
nodes = {}
for cat in cats:
nodes[cat['id']] = cat
cat['children'] = []
# Step 2: For each category, add it to the parent's children
for index, cat in nodes.items():
if cat['parent_id']:
nodes[cat['parent_id']]['children'].append(cat)
# Step 3: Keep only those that do not have a parent
cats = [c for c in nodes.values() if not c['parent_id']]
请注意,每个节点都有一个名为'children'
的属性,该属性可以是空列表,也可以是包含一个或多个节点的列表。如果您不想要空的子列表
,只需在步骤2和步骤2之间从节点
中的每个类别中删除它们即可
还请注意,上面假设实际存在具有给定父id的节点。最后,请注意,当id为零的节点存在时,
if not c['parent_id']
也将为真,因此如果出现这种情况,您需要记住。这里有一个相当简洁的解决方案:
cats = [{'parent_id': False, 'id': 1, 'title': u'All'},
{'parent_id': False, 'id': 2, 'title': u'Toys'},
{'parent_id': 2, 'id': 3, 'title': u'Toypads'},
{'parent_id': 3, 'id': 4, 'title': u'Green'},]
cats_dict = dict((cat['id'], cat) for cat in cats)
for cat in cats:
if cat['parent_id'] != False:
parent = cats_dict[cat['parent_id']]
parent.setdefault('children', []).append(cat)
cats = [cat for cat in cats if cat['parent_id'] == False]
请注意,与False的比较通常是不必要的,但如果您有一只id为0或父id为0的猫,则应在此处使用它们。在这种情况下,对于没有父id的猫,我将使用
None
而不是False
。以下是一个相当简洁的解决方案:
cats = [{'parent_id': False, 'id': 1, 'title': u'All'},
{'parent_id': False, 'id': 2, 'title': u'Toys'},
{'parent_id': 2, 'id': 3, 'title': u'Toypads'},
{'parent_id': 3, 'id': 4, 'title': u'Green'},]
cats_dict = dict((cat['id'], cat) for cat in cats)
for cat in cats:
if cat['parent_id'] != False:
parent = cats_dict[cat['parent_id']]
parent.setdefault('children', []).append(cat)
cats = [cat for cat in cats if cat['parent_id'] == False]
请注意,与False的比较通常是不必要的,但如果您有一只id为0或父id为0的猫,则应在此处使用它们。在这种情况下,对于没有父id的猫,我将使用
None
而不是False
。您能再次解释一下您想要什么吗?我不能理解你的孩子们。。。它是如此嵌套,你想做什么?你能再解释一下你想要什么吗?我不能理解你的孩子们。。。它是如此嵌套,你想做什么?非常感谢。这正是我所需要的。对于没有父母的猫,我会使用None
,另外还可以使用is
测试:如果猫['parent\u id']不是无:
非常感谢。这正是我所需要的。对于没有父猫的猫,我会使用None
,如果猫['parent\u id']不是None: