| 211 | | == countoccurrences() / countdistinct() == |
| 212 | | |
| 213 | | Written by Arnar Birgisson and shared on the IrcChannel. |
| 214 | | |
| 215 | | {{{ |
| 216 | | #!python |
| 217 | | def countoccurrences(numbers, minlength=0): |
| 218 | | """Takes a list of integers, in the range of 0..n and returns a list of integers |
| 219 | | where i-th item is the number of times i appears in the input list. |
| 220 | | |
| 221 | | If minlength is specified and n+1 < minlength, the returned list is |
| 222 | | right-padded with zeroes to make it contain minlength items. |
| 223 | | |
| 224 | | Examples: |
| 225 | | >>> countoccurrences([0,3,1,2,1,1,3,5]) |
| 226 | | [1,3,1,2,0,1] |
| 227 | | >>> countoccurrences([0,3,1,2,1,1,3,5], 10) |
| 228 | | [1,3,1,2,0,1,0,0,0,0] |
| 229 | | """ |
| 230 | | # TODO come up with a better name |
| 231 | | counts = [0] * max(max(numbers)+1, minlength) |
| 232 | | for x in numbers: |
| 233 | | counts[x] += 1 |
| 234 | | return counts |
| 235 | | }}} |
| 236 | | |
| 237 | | === Example usage === |
| 238 | | |
| 239 | | {{{ |
| 240 | | #!xml |
| 241 | | <py:with vars="counts = countoccurrences([p.status.value for p in subdir.job.pages], 3)"> |
| 242 | | <td><span style="color: #e18f01;">${counts[0]}</span></td> |
| 243 | | <td><span style="color: #249f0b;">${counts[1]}</span></td> |
| 244 | | <td><span style="color: #ae0a0a;">${counts[2]}</span></td> |
| 245 | | </py:with> |
| 246 | | }}} |
| 247 | | |
| 248 | | === Similar version with a dict, counts any hashable types === |
| 249 | | |
| 250 | | The previous function can only count occurrences of numbers. |
| 251 | | This counts occurrences of any hashable types and returns a dict instead of a list. |
| 252 | | {{{ |
| 253 | | #!python |
| 254 | | def countitemoccurrences(items, requireditems=[]): |
| 255 | | """Takes a list of hashable items and returns a dict whose keys are those |
| 256 | | items and the values are the counts of how many times each item appers in the list. |
| 257 | | |
| 258 | | If the list requireditems is specified it's values are guaranteed to be keys |
| 259 | | in the resulting dict, even if they don't appear in items in which case the count will be 0 |
| 260 | | |
| 261 | | Examples: |
| 262 | | >>> counttypes('blue green green'.split(), 'blue red green'.split()) |
| 263 | | {'blue': 1, 'green': 2, 'red': 0} |
| 264 | | """ |
| 265 | | counts = dict() |
| 266 | | for i in requireditems: |
| 267 | | counts[i] = 0 |
| 268 | | for i in items: |
| 269 | | counts[i] = counts.get(i, 0) + 1 |
| 270 | | return counts |
| 271 | | }}} |
| 272 | | |
| 273 | | === Generic version based on `itertools.groupby` === |
| | 211 | === countoccurrences === |
| | 212 | |
| | 213 | Written by [http://www.cmlenz.net/ Christopher Lenz] with a small bugfix by Arnar. |
| 302 | | return dict([(g, 0) for g in groups] + |
| 303 | | [(g, len(list(l))) for g, l in groupby(iterable, key=key)]) |
| | 242 | d = dict([(g, 0) for g in groups]) |
| | 243 | for g, l in groupby(iterable, key=key): |
| | 244 | d[g] = len(list(l)) + d.get(g, 0) |
| | 245 | return d |