将 F 表达式的列表相加。

huangapple go评论146阅读模式
英文:

Sum together list of F expressions

问题

有没有一种方法可以指定(在注释或汇总中)一系列F表达式应该在不手动输入F("first_prop") + F("second_prop") + ...的情况下相加在一起?

我想要类似于Python的sum()函数的功能,允许您传递可迭代对象并获取可迭代对象中值的总和,即sum([1,2,3])返回6

具体来说,我想要类似于以下的功能:

class Tree(TimeStampedModel):
  leaf_count = models.IntegerField()
  branch_count = models.IntegerField()

Tree.objects.create(leaf_count=60, branch_count=8)
Tree.objects.create(leaf_count=30, branch_count=3)

# 现在我想要使用我的虚构的IterableSum聚合器注释一个组合计数
combined_sums = list(
  Tree.objects.all().annotate(
    combined_count=IterableSum(fields=[F("leaf_count"), F("branch_count")])
  ).values_list("combined_count", flat=True)
)

combined_sums # [68, 33]

我该如何实现这个?

英文:

Is there a way to specify (in an annotation or aggregation) that a sequence of F expressions should be summed together without manually typing out F("first_prop") + F("second_prop") + ...?

I want something similar to how python's sum() function allows you to pass an iterable and get the sum of the values in the iterable i.e. sum([1,2,3]) returns 6.

Concretely, I want something that looks like this:

class Tree(TimeStampedModel):
  leaf_count = models.IntegerField()
  branch_count = models.IntegerField()

Tree.objects.create(leaf_count=60, branch_count=8)
Tree.objects.create(leaf_count=30, branch_count=3)

# now I want to annotate a combined count using my imaginary IterableSum aggregator
combined_sums = list(
  Tree.objects.all().annotate(
    combined_count=IterableSum(fields=[F("leaf_count"), F("branch_count")])
  ).values_list("combined_count", flat=True)
)

combined_sums # [68, 33]

How can I achieve this?

答案1

得分: 2

唯一的问题在于sum的初始值是0。你可以使用functools库中的reduce函数:

from functools import reduce
from operator import add

from django.db.models import F

combined_sums = list(
    Tree.objects.values(
        combined_count=reduce(add, [F('leaf_count'), F('branch_count')]),
        flat=True,
    )
)

严格来说,这甚至不是必要的,你可以直接使用sum,因为它会将0F('leaf_count')相加:

from django.db.models import F

combined_sums = list(
    Tree.objects.values(
        combined_count=sum([F('leaf_count'), F('branch_count')]),
        flat=True,
    )
)

然后这将在查询中有一个+ 0,可能不是理想的。这是因为sum不仅仅可以对整数求和,实际上,你可以对F对象进行求和:

sum([F('foo'), F('bar')])
英文:

The only problem with sum is that it starts with 0 as initial value. You can you can use reduce from functools:

<pre><code>from functools import reduce
from operator import add

from django.db.models import F

combined_sums = list(
Tree.objects.values(
combined_count=reduce(add, [F('leaf_count'), F('branch_count')]),
flat=True,
)
)</code></pre>

although strictly speaking, that is not even necessary, you can just use sum, since it will add up 0 with F(&#39;leaf_count&#39;):

<pre><code>from django.db.models import F

combined_sums = list(
Tree.objects.values(
combined_count=sum([F('leaf_count'), F('branch_count')]),
flat=True,
)
)</code></pre>

Then this will have a + 0 in the query, which might not be ideal.

This is because sum does not sum only integers, indeed, you can for example sum F objects:

In [11]: sum([F(&#39;foo&#39;), F(&#39;bar&#39;)])
Out[11]: &lt;CombinedExpression: Value(0) + F(foo) + F(bar)&gt;

huangapple
  • 本文由 发表于 2023年3月7日 23:49:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75664215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定