Mercurial > sat_legacy_website
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() |