Вы можете использовать накопление для формирования групп, вычисляя относительный индекс каждого фрукта в своей группе. Это позволяет вам установить максимальный размер группы и сбросить относительный индекс либо при изменении фруктов r при достижении максимума.
С помощью этой группировки вы можете назначать последовательные индексы на основе первого элемента каждой группы. (снова используя накопление):
fruits = ['Apples','Bananas','Bananas','Pear','Pear','Pear','Pear','Melon','Melon',
'Melon','Melon','Melon','Melon','Orange','Orange','Orange','Orange','Orange',
'Orange','Orange','Orange','Orange']
from itertools import accumulate
maxGroup = 4
indexes = range(len(fruits))
byGroup = accumulate(indexes,lambda i,f: (i+1)*(f>0 and i<maxGroup-1 and fruits[f-1]==fruits[f]))
indexes = [i-1 for i in accumulate(int(g==0) for g in byGroup)]
indexAndFruit = [(i,f) for i,f in zip(indexes,fruits)]
вывод:
for i,f in indexAndFruit: print(i,f)
0 Apples
1 Bananas
1 Bananas
2 Pear
2 Pear
2 Pear
2 Pear
3 Melon
3 Melon
3 Melon
3 Melon
4 Melon
4 Melon
5 Orange
5 Orange
5 Orange
5 Orange
6 Orange
6 Orange
6 Orange
6 Orange
7 Orange
Чтобы проиллюстрировать, как это работает, давайте посмотрим, что будет производить итератор byGroup:
[0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 0]
Каждая позиция, где индексация начинается с нуля, соответствует изменению фруктов или относительному индексу, достигающему максимума
Нули в этом списке соответствуют началу групп. Пометка их как 1 с 0 для других индексов даст следующий результат:
[1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
Если мы запустим кумулятивную сумму этих начальных позиций, мы получим (основанные на одном) индексы:
[1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8]
минус 1 дает нам нужные индексы, которые нам нужно только объединить с фруктами (используя zip):
[0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7]