在Django中生成给定QuerySet的所有可能子集

时间:2010-04-11 20:44:54

标签: python django django-queryset

这只是一个例子,但给出了以下模型:

class Foo(models.model):
    bar = models.IntegerField()

    def __str__(self):
        return  str(self.bar)

    def __unicode__(self):
        return str(self.bar)

以下QuerySet对象:

foobar = Foo.objects.filter(bar__lt=20).distinct()

(意思是一组带有Foo的唯一bar <= 20模型),如何生成foobar的所有可能子集?理想情况下,我希望进一步限制子集,以便对x的每个子集foobarf.bar中所有x的总和(其中f }是Foo类型的模型,介于某个最大值和最小值之间。

因此,例如,给定以下foobar实例:

>> print foobar
[<Foo: 5>, <Foo: 10>, <Foo: 15>]

min=5max=25,我想构建一个对象(最好是QuerySet,但可能是一个列表),如下所示:

[[<Foo: 5>], [<Foo: 10>], [<Foo: 15>], [<Foo: 5>, <Foo: 10>],
 [<Foo: 5>, <Foo: 15>], [<Foo: 10>, <Foo: 15>]]

我已经尝试过itertools,但它似乎并不特别适合我的需求。

认为这可以通过复杂的QuerySet完成,但我不知道如何开始。

2 个答案:

答案 0 :(得分:3)

S = [list(itertools.combinations(foobar,i)) for i in xrange(1, len(foobar))]

它生成非平面列表。您可以通过以下方式展平它:

list(itertools.chain.from_iterable(S))

答案 1 :(得分:1)

这将为您提供foobar from itertools import combinations [j for i in range(len(foobar)+1) for j in combinations(foobar,i)] (作为列表)

from itertools import combinations
[j for i in range(len(foobar)+1) for j in combinations(foobar,i)
 if minval <= sum(f.bar for f in j) <= maxval]

为minval和maxval添加过滤器给出:

>>> from itertools import combinations
>>> class Foo(object):
...     def __init__(self, bar):
...         self.bar=bar
...     def __repr__(self):
...         return  "<Foo: %s>"%self.bar
... 
>>> foobar=[Foo(5),Foo(10),Foo(15)]
>>> minval=5
>>> maxval=25
>>> [j for i in range(len(foobar)+1) for j in combinations(foobar,i) 
     if minval <= sum(f.bar for f in j) <= maxval]
[(<Foo: 5>,), (<Foo: 10>,), (<Foo: 15>,), (<Foo: 5>, <Foo: 10>), (<Foo: 5>, <Foo: 15>), (<Foo: 10>, <Foo: 15>)]

让我们创建一个类并试一试

>>> [list(j) for i in range(len(foobar)+1) for j in combinations(foobar,i) if minval <= sum(f.bar for f in j) <= maxval ]
[[<Foo: 5>], [<Foo: 10>], [<Foo: 15>], [<Foo: 5>, <Foo: 10>], [<Foo: 5>, <Foo: 15>], [<Foo: 10>, <Foo: 15>]]

如果你需要列表而不是元组,那么在

中添加它也是微不足道的
{{1}}