[Django]-Django merge 2 querysets in staggered/alternating fashion?

3👍

You can get the result you need using zip_longest, chain and filter together.

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

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

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)

That’s almost what we want, but we’ve got Nones at the end if one queryset is shorter than the other. We can get rid of them with filter (ifilter in Python 2).

Leave a comment