- Author:
- jacobian
- Posted:
- February 25, 2007
- Language:
- Python
- Version:
- Pre .96
- Score:
- 20 (after 22 ratings)
People -- and by "people" I mean Jeff Croft -- often ask about how to split a list into multiple lists (usually for presenting as columns in a template).
These template tags provide two different ways of splitting lists -- on "vertically", and the other "horizontally".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | """
Template tags for working with lists.
You'll use these in templates thusly::
{% load listutil %}
{% for sublist in mylist|parition:"3" %}
{% for item in mylist %}
do something with {{ item }}
{% endfor %}
{% endfor %}
"""
from django import template
register = template.Library()
@register.filter
def partition(thelist, n):
"""
Break a list into ``n`` pieces. The last list may be larger than the rest if
the list doesn't break cleanly. That is::
>>> l = range(10)
>>> partition(l, 2)
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
>>> partition(l, 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> partition(l, 4)
[[0, 1], [2, 3], [4, 5], [6, 7, 8, 9]]
>>> partition(l, 5)
[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
"""
try:
n = int(n)
thelist = list(thelist)
except (ValueError, TypeError):
return [thelist]
p = len(thelist) / n
return [thelist[p*i:p*(i+1)] for i in range(n - 1)] + [thelist[p*(i+1):]]
@register.filter
def partition_horizontal(thelist, n):
"""
Break a list into ``n`` peices, but "horizontally." That is,
``partition_horizontal(range(10), 3)`` gives::
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10]]
Clear as mud?
"""
try:
n = int(n)
thelist = list(thelist)
except (ValueError, TypeError):
return [thelist]
newlists = [list() for i in range(n)]
for i, val in enumerate(thelist):
newlists[i%n].append(val)
return newlists
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Thanks so much for this, Jacob!
Just a small error in the docstring up top...
I think that third line should be:
Right?
#
Err, I mean:
#
partition_horizontal does not do what its docstring suggests:
Assuming the implementation is correct, a more efficient implementation uses 'extended slices' i.e. (without error-checking):
#
If what spencermah said is true, one could collapse this into one line:
Firstly, we have to pass a name since it is an anonymous function, secondly we pass the function with lambda style defining. Simple as pie.
#
As noted above the docstring for partition_horizontal is not what the actually implementation is generating. I have corrected the implementation to work as noted.
By the way range(10) will never give you a 10 ;)
@register.filter def partition_horizontal(thelist, n): """ Break a list into
n
peices, but "horizontally." That is,partition_horizontal(range(10), 3)
gives::Eh, the highlighting didn't seem to work too well, lol.
#
I modified the vertical filter so that if the list doesn't divide evenly, the last list would be the shortest (rather than longest). I thought this might be helpful to others.
I took line 44:
And replaced it with this:
#
Typo on line 7: "parition" > "partition"
#
How about this:
#
Please login first before commenting.