我有一个sqlalchemy类别表,如下所示:
id | parent_id | name
1 | 0 | license
2 | 1 | Digital Media
3 | 1 | Advertising
4 | 2 | Email Marketing
我的目标是将其转换为嵌套字典或列表,我可以在Flask模板中循环。下面的代码有效但对我来说看起来很混乱。有没有办法可以改进它?
categories = Category.query.all()
roots = [root for root in categories if root.parent_id == 1]
items = []
for root in roots:
items.append({'root': root.name, 'subcategories': []})
for category in categories:
if category.parent_id == root.id:
items[-1]['subcategories'].append(category.name)
答案 0 :(得分:1)
如果您只想更简洁地编写您提出的逻辑,请查看以下内容:
categories = Category.query.all()
items = [{'root': root.name, 'subcategories':
[category.name for category in categories if category.parent_id == root.id]
}
for root in categories if root.parent_id == 1]
请注意,这在O(N 2 )中运行,其中N是类别数。如果您希望更好地执行此操作,则可以将parent_id
映射到类别。例如:
categories = Category.query.all()
category_by_parent_id = {}
for category in categories:
if category.parent_id not in category_by_parent_id:
category_by_parent_id[category.parent_id] = [category]
else:
category_by_parent_id[category.parent_id].append(category)
items = [{'root': root.name, 'subcategories': category_by_parent_id[root.id] if root.id in category_by_parent_id else []} for root in category_by_parent_id[1]]
上述工作是将每个parent_id映射设置为具有该父ID的类别列表。然后我们循环遍历所有根类别(字典中parent_id 1的列表),并将子类别设置为等于根id的类别列表。如果root的id不在字典中,我们会将子类别设置为空列表。现在这个操作的运行时是O(N),因为我们只运行列表两次,而O(2N)= O(N)。
使用集合中的默认字典可以更好地完成此方法。 default_dict
需要指定默认值,并且假定当前不在字典中的所有键都具有该默认值。例如,a = default_dict(0); print(a[1])
将打印0,因为这是为列表指定的默认值,而键1当前不存在。这可以用来简化上面的方法:
from collection import default_dict
categories = Category.query.all()
category_by_parent_id = default_dict([])
for category in categories:
category_by_parent_id[category.parent_id].append(category)
items = [{'root': root.name, 'subcategories': category_by_parent_id[root.id]} for root in category_by_parent_id[1]]
答案 1 :(得分:0)
您可以嵌套列表推导,因此您无需在roots
和categories
内进行双循环。
categories = Category.query.all()
roots = [root for root in categories if root.parent_id == 1]
items = [
{
'root': root.name,
'subcategories': [
category.name
for category in categories
if category.parent_id == root.id
]
}
for root in roots
]