comparison sat_website/templatetags/partition.py @ 0:9305c6458e2f

initial commit
author Goffi <goffi@goffi.org>
date Sat, 28 Jul 2012 20:36:32 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:9305c6458e2f
1 """
2 (c) Smiley Chris 2007
3
4 This code comes from Django snippets ( http://djangosnippets.org/snippets/401/ )
5 According to the Terms of Service ( http://djangosnippets.org/about/tos/ ), the code can be freely used
6
7 Template filters to partition lists into rows or columns.
8
9 A common use-case is for splitting a list into a table with columns::
10
11 {% load partition %}
12 <table>
13 {% for row in mylist|columns:3 %}
14 <tr>
15 {% for item in row %}
16 <td>{{ item }}</td>
17 {% endfor %}
18 </tr>
19 {% endfor %}
20 </table>
21 """
22
23 from django.template import Library
24
25 register = Library()
26
27 def rows(thelist, n):
28 """
29 Break a list into ``n`` rows, filling up each row to the maximum equal
30 length possible. For example::
31
32 >>> l = range(10)
33
34 >>> rows(l, 2)
35 [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
36
37 >>> rows(l, 3)
38 [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]
39
40 >>> rows(l, 4)
41 [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
42
43 >>> rows(l, 5)
44 [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
45
46 >>> rows(l, 9)
47 [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [], [], [], []]
48
49 # This filter will always return `n` rows, even if some are empty:
50 >>> rows(range(2), 3)
51 [[0], [1], []]
52 """
53 try:
54 n = int(n)
55 thelist = list(thelist)
56 except (ValueError, TypeError):
57 return [thelist]
58 list_len = len(thelist)
59 split = list_len // n
60
61 if list_len % n != 0:
62 split += 1
63 return [thelist[split*i:split*(i+1)] for i in range(n)]
64
65 def rows_distributed(thelist, n):
66 """
67 Break a list into ``n`` rows, distributing columns as evenly as possible
68 across the rows. For example::
69
70 >>> l = range(10)
71
72 >>> rows_distributed(l, 2)
73 [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
74
75 >>> rows_distributed(l, 3)
76 [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]
77
78 >>> rows_distributed(l, 4)
79 [[0, 1, 2], [3, 4, 5], [6, 7], [8, 9]]
80
81 >>> rows_distributed(l, 5)
82 [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
83
84 >>> rows_distributed(l, 9)
85 [[0, 1], [2], [3], [4], [5], [6], [7], [8], [9]]
86
87 # This filter will always return `n` rows, even if some are empty:
88 >>> rows(range(2), 3)
89 [[0], [1], []]
90 """
91 try:
92 n = int(n)
93 thelist = list(thelist)
94 except (ValueError, TypeError):
95 return [thelist]
96 list_len = len(thelist)
97 split = list_len // n
98
99 remainder = list_len % n
100 offset = 0
101 rows = []
102 for i in range(n):
103 if remainder:
104 start, end = (split+1)*i, (split+1)*(i+1)
105 else:
106 start, end = split*i+offset, split*(i+1)+offset
107 rows.append(thelist[start:end])
108 if remainder:
109 remainder -= 1
110 offset += 1
111 return rows
112
113 def columns(thelist, n):
114 """
115 Break a list into ``n`` columns, filling up each column to the maximum equal
116 length possible. For example::
117
118 >>> from pprint import pprint
119 >>> for i in range(7, 11):
120 ... print '%sx%s:' % (i, 3)
121 ... pprint(columns(range(i), 3), width=20)
122 7x3:
123 [[0, 3, 6],
124 [1, 4],
125 [2, 5]]
126 8x3:
127 [[0, 3, 6],
128 [1, 4, 7],
129 [2, 5]]
130 9x3:
131 [[0, 3, 6],
132 [1, 4, 7],
133 [2, 5, 8]]
134 10x3:
135 [[0, 4, 8],
136 [1, 5, 9],
137 [2, 6],
138 [3, 7]]
139
140 # Note that this filter does not guarantee that `n` columns will be
141 # present:
142 >>> pprint(columns(range(4), 3), width=10)
143 [[0, 2],
144 [1, 3]]
145 """
146 try:
147 n = int(n)
148 thelist = list(thelist)
149 except (ValueError, TypeError):
150 return [thelist]
151 list_len = len(thelist)
152 split = list_len // n
153 if list_len % n != 0:
154 split += 1
155 return [thelist[i::split] for i in range(split)]
156
157 register.filter(rows)
158 register.filter(rows_distributed)
159 register.filter(columns)
160
161 def _test():
162 import doctest
163 doctest.testmod()
164
165 if __name__ == "__main__":
166 _test()