Для записи, функциональный ответ:
>>> L = [1,1,1,1,2,2,2,2,3,3,4,5,5]
>>> import functools
>>> >>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc,1)] if e<=len(acc) else acc+[0 for _ in range(e-len(acc)-1)]+[1], L, [])
[4, 4, 2, 1, 2]
Будет чище, если вы посчитаете нули тоже:
>>> functools.reduce(lambda acc, e: [v+(i==e) for i, v in enumerate(acc)] if e<len(acc) else acc+[0 for _ in range(e-len(acc))]+[1], L, [])
[0, 4, 4, 2, 1, 2]
Объяснение:
- мы начинаем с пустого
acc
списка;
- если следующий элемент
e
из L
меньше, чем размер acc
, мы просто обновляем этот элемент: v+(i==e)
означает v+1
, если индекс i
из acc
является текущим элемент e
, в противном случае предыдущее значение v
;
- если следующий элемент
e
из L
больше или равен размеру acc
, мы должны расширить acc
, чтобы разместить новый 1
.
Элементы не должны быть отсортированы (itertools.groupby
). Вы получите странные результаты, если у вас будут отрицательные числа.