I have a (long) list in which zeros and ones appear at random:
list_a = [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1]
I want to get the list_b
If you want a compact native Python solution that is probably the most memory efficient, although not the fastest (see the comments), you could draw extensively from itertools
:
>>> from itertools import groupby, accumulate, chain
>>> list(chain.from_iterable(accumulate(g) for _, g in groupby(list_a, bool)))
[1, 2, 3, 0, 1, 2, 0, 1, 0, 1, 2, 3]
The steps here are: group the list into sublists based on presence of 0
(which is falsy), take the cumulative sum of the values within each sublist, flatten the sublists.
As Stefan Pochmann comments, if your list is binary in contents (like consisting of only 1
s and 0
s only) then you don't need to pass a key to groupby()
at all and it will fall back on the identity function. This is ~30% faster than using bool
for this case:
>>> list(chain.from_iterable(accumulate(g) for _, g in groupby(list_a)))
[1, 2, 3, 0, 1, 2, 0, 1, 0, 1, 2, 3]