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 a range 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]

Tags:

Python

List