Finding longest run in a list
This is possible using itertools
:
from itertools import groupby, chain
x_list = [1, 1, 2, 3, 3, 3]
gen = (range(len(list(j)), 0, -1) for _, j in groupby(x_list))
res = list(chain.from_iterable(gen))
Result
[2, 1, 1, 3, 2, 1]
Explanation
- First use
itertools.groupby
to group identical items in your list. - For each item in your
groupby
, create arange
object which counts backwards from the length of the number of consecutive items to 1. - Turn this all into a generator to avoid building a list of lists.
- Use
itertools.chain
to chain the ranges from the generator.
Performance note
Performance will be inferior to @Aran-Fey's solution. Although itertools.groupby
is O(n), it makes heavy use of expensive __next__
calls. These do not scale as well as iteration in simple for
loops. See itertools docs for groupby
pseudo-code.
If performance is your main concern, stick with the for
loop.
Here's a simple solution that iterates over the list backwards and increments a counter each time a number is repeated:
last_num = None
result = []
for num in reversed(x_list):
if num != last_num:
# if the number changed, reset the counter to 1
counter = 1
last_num = num
else:
# if the number is the same, increment the counter
counter += 1
result.append(counter)
# reverse the result
result = list(reversed(result))
Result:
[2, 1, 1, 3, 2, 1]