Dada uma lista de elementos repetitivos, escreva um programa python para reduzir a repetição dos elementos e converter a repetição em um elemento de tupla da lista contendo o elemento repetido e o número de vezes que ele se repetiu. Assim, convertendo a lista fornecida em uma lista de tuplas.

Exemplos:

Entrada: [1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4]
 Saída: [(1, 3), (2, 1), (3, 3), (4, 4 )]
Entrada: ['alice', 'alice', 'bob']
 Saída: [('alice', 2), ('bob', 1)]

Abordagem # 1: força bruta
Esta é uma abordagem ingênua para diminuir a lista. É necessário outra lista, dizer 'tup_list'. Inicialize o índice para 0 e use um loop para verificar quantas vezes cada elemento exclusivo da lista é repetido. Depois de encontrar o elemento e sua contagem de repetição, acrescente-o à lista na forma de uma tupla.

def shrinkList(lst): 
    tup_list = [] 
    i, index = 0, 0
    while(index < len(lst)): 
        element_count = 0
        while(i < len(lst) and lst[i] == lst[index]): 
            element_count += 1
            i += 1
        tup_list.append((lst[index], element_count)) 
        index += element_count 
          
    return tup_list 
lst = [1, 1, 1, 2, 2, 3, 3, 4] 
print(shrinkList(lst)) 
Resultado:
[(1, 3), (2, 2), (3, 2), (4, 1)]

 
Abordagem # 2: força bruta alternativa
Esta é outra abordagem de força bruta que usa loop for para percorrer a lista. Ele usa uma variável 'prev_element' para armazenar o elemento anterior. Primeiro, ele verifica se este é o primeiro elemento exclusivo ou não; em caso afirmativo, ele incrementa o contador e armazena o elemento em prev_element. Se o elemento se repetir, basta incrementar o contador. Se todos esses casos não forem verdadeiros, apenas acrescente o elemento anterior e conte como tupla para tup_list.



def shrinkList(lst): 
    prev_element = None
    count = 0
    tup_list = [] 
  
    for ele in lst: 
        if (prev_element == ele):  
            count += 1
            elif (prev_element is None): 
            count += 1
            prev_element = ele 
            else: 
            tup_list.append((prev_element, count)) 
            count = 1
            prev_element = ele 
  
    tup_list.append((prev_element, count)) 
    return tup_list 
lst = [1, 1, 1, 2, 2, 3, 3, 4] 
print(shrinkList(lst)) 
Resultado:
[(1, 3), (2, 2), (3, 2), (4, 1)]

 
Abordagem nº 3: usando Itertools.groupby()
Esta é uma abordagem mais pythônica para resolver o problema fornecido. Eles itertools.groupby()fazem um iterador que retorna chaves e grupos consecutivos do iterável. Ele agrupa elementos semelhantes e retorna os elementos e sua contagem como uma lista de tuplas.

from itertools import groupby 
  
def shrinkList(lst): 
    return ([(element, len(list(i))) 
    for element, i in groupby(lst)]) 
lst = [1, 1, 1, 2, 2, 3, 3, 4] 
print(shrinkList(lst)) 
Resultado:
[(1, 3), (2, 2), (3, 2), (4, 1)]