我有一个有趣的编程问题,我确信它有许多非常有趣的解决方案,我希望有人能够深入了解我可以采取的良好方向。
我在Django工作,我有一个对象QuerySet和一组过滤器。我想找到一个在所有过滤器中存活的对象子集,但这并不总是可行的,所以我想对查询集进行排序,以便在最重要的过滤器之后存在的对象总是会被过滤掉。我为每个过滤器定义了重要性级别。
所以,在一个抽象的层面上,给定一组对象和一组加权约束,我想要一个有序的对象列表,通过它们实现的权重。
例如, 给出一组单词:
{'Almond', 'Red', 'Apple', 'Gargle', 'Anyone'}
一组有价值的过滤器:
- Starts with A, worth 10 points
- Ends with E, worth 5 points
- 6 letters long, worth 3 points
返回以下数组,并带有相关的得分:
[['Anyone',18],['Apple',15],['Almond', 13],['Gargle',8],['Red',0]]
由于这些是Django中的对象和过滤器,我还想使用尽可能查询集函数而不是循环来改善运行时和复杂性(我正在使用PostgreSQL,因此任何PostgreSQL特定的解决方案都可以)。
基本上,如果我有n个对象和f过滤器,我希望实现比O(nf+nlogn)
更好的复杂性,或者至少优化Django的解决方案。
答案 0 :(得分:2)
from django.db.models import CharField, IntegerField, Case, When, Q
from django.db.models.functions import Length
# You can register function as a transform
CharField.register_lookup(Length, 'length')
filters = [
(Q(name__startswith='A'), 10),
(Q(name__endswith='E'), 5),
(Q(name__length=6), 3),
]
Item.objects.annotate(
# sum, not Sum
tot_score=sum(Case(When(filter, then=score),
default=0,
output_field=IntegerField())
for filter, score in filters)
).values_list('name', 'tot_score').order_by('-tot_score')