Python: remover elementos duplicados mantendo ordem

No Python, um dos jeitos de deduplicar uma lista é o seguinte:

lista_duplicada = ['Maçã', 'Banana', 'Maçã', 'Abacaxi']
lista_deduplicada = list(set(lista_duplicada))
print(lista_deduplicada)  # ['Abacaxi', 'Banana', 'Maçã']

Transformar num set, que automaticamente elimina duplicados, e depois transformar de volta numa lista. Faz sentido, mas tem uma armadilha que pode causar problemas: a ordem da nova lista não é garantida. Sets são hash tables, e não têm conceito de ordem. Se isso não afeta o programa é um jeito bem conciso e eficiente de deduplicar a lista, mas se afetar, temos que procurar uma alternativa.

Pra gerar uma lista deduplicada na mesma ordem que a lista original (mantendo o primeiro elemento visto), podemos fazer o seguinte:

def deduplicar_mantendo_ordem(lista):
    elementos_vistos = []
    nova_lista = []
    for el in lista:
        if el not in elementos_vistos:
            elementos_vistos.append(el)
            nova_lista.append(el)
    return nova_lista

Essa função é clara, mas não é a mais rápida. Segundo testes do Peter Bengtsson, o seguinte jeito é o mais rápido pro Python 3.6+:

def deduplicar_mantendo_ordem(lista):
    return list(dict.fromkeys(lista))

Mas como ele usa hash tables internamente, sobe umTypeError: unhashable type: 'set'se você tenta deduplicar uma lista com elementos cujo hash não pode ser calculado (como sets, listas e dicionários; em geral, objetos mutáveis). Se sua lista tiver esses elementos, a seguinte é uma alternativa:

def deduplicar_mantendo_ordem_unhashable(lista):
    vistos = list()
    return [x for x in lista if x not in vistos and not vistos.append(x)]


lista_duplicada = [{'Maçã'}, 'Banana', {'Maçã'}, 'Abacaxi']
print(deduplicar_mantendo_ordem_unhashable(lista_duplicada))
Show Comments

Get the latest posts delivered right to your inbox.