问题描述
在我的Django应用中,我有两个 same 对象的查询集.我知道我可以像这样使用itertools和chain合并2个查询集:
In my Django app I have 2 querysets of the same object. I know I can merge 2 querysets using itertools and chain like so:
from itertools import chain
list(chain(first_queryset, second_queryset))
但是这会输出一个新的查询集,其中整个第一个查询集后面都跟着整个第二个查询集,如下所示:
But this outputs a new queryset where the entire first one is followed by the entire second one like so:
[<first_queryset_1st_instance>, <first_queryset_2nd_instance>, <first_queryset_3rd_instance>, <second_queryset_1st_instance>, <second_queryset_2nd_instance>, <second_queryset_3rd_instance>]
但是,我确实需要一个在每个查询集之间交替的输出,而不是像这样在整个第一个查询集的末尾附加整个第二个查询集:
However, I really need an output that is alternating between each queryset instead of just appending the entire second queryset at the end of the first one like so:
[<first_queryset_1st_instance>, <second_queryset_1st_instance>,<first_queryset_2nd_instance>, <second_queryset_2nd_instance>, <first_queryset_3rd_instance>, <second_queryset_3rd_instance>]
在python/django中执行此操作的最佳方法是什么?
What's the best way I can do this in python/django?
推荐答案
您可以使用 zip_longest
, 链
和 过滤器
.
You can get the result you need using zip_longest
, chain
and filter
together.
让我们将查询集称为 p
和 q
.然后您会这样做:
Lets call the querysets p
and q
. Then you would do:
# Python 3.x
from itertools import chain, zip_longest
combined = list(filter(lambda x: x is not None, chain(*zip_longest(p, q))))
# Python 2.7
from itertools import chain, ifilter, izip_longest
combined = list(ifilter(lambda x: x is not None, chain(*izip_longest(p, q))))
让我们解释一下它是如何工作的.首先, zip_longest
(在Python 2中为 izip_longest
)将查询集压缩在一起.您需要 zip_longest
而不是 zip
,以便在较短的查询集完成后继续输出.
Let's explain how it works. First, zip_longest
(izip_longest
in Python 2) zips the querysets together. You want zip_longest
instead of zip
, so that the output continues after the shorter queryset has finished.
这将创建一个可迭代的内容,例如:
This creates an iterable like:
((p[0], q(0)), (p[1], q[1]), (p[2], q[2]), ..., (p[9], q[9]), (p[10], None))
请注意,这是一个可重复的元组,但是您需要一个平面列表.因此,接下来我们使用 chain
,使用 *
运算符解压缩 zip_longest
的结果.
Note this is an iterable of tuples, but you want a flat list. So next we use chain
, using the *
operator to unpack the result of zip_longest
.
这会创建一个可迭代的对象.
This creates an iterable like.
(p[0], q[0], p[1], q[1], ..., p[9], q[9], p[10], None)
这几乎是我们想要的,但是如果一个查询集比另一个查询集短,我们最后将得到 None
.我们可以使用 filter
(在Python 2中为 ifilter
)摆脱它们.
That's almost what we want, but we've got None
s at the end if one queryset is shorter than the other. We can get rid of them with filter
(ifilter
in Python 2).
这篇关于Django以交错/交替的方式合并2个查询集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!