【问题标题】:Generating all possible subsets of a given QuerySet in Django在 Django 中生成给定 QuerySet 的所有可能子集
【发布时间】:2010-04-11 20:44:54
【问题描述】:

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

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 的所有可能子集?理想情况下,我想进一步限制子集,以便对于foobar 的每个子集xx 中所有f.bar 的总和(其中fFoo 类型的模型)介于某个最大值和最小值之间。

因此,例如,给定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 来完成,但我不知道如何开始。

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:
    S = [list(itertools.combinations(foobar,i)) for i in xrange(1, len(foobar))]
    

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

    list(itertools.chain.from_iterable(S))
    

    【讨论】:

      【解决方案2】:

      这将为您提供foobarpowerset(作为列表)

      from itertools import combinations
      [j for i in range(len(foobar)+1) for j in combinations(foobar,i)]
      

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

      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]
      

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

      >>> 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>]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-24
        • 1970-01-01
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 2013-08-11
        • 2017-11-23
        相关资源
        最近更新 更多