Remoção de duplicados em listas

Eu preciso escrever um programa para verificar se uma lista tem alguma duplicata e se ele a remove e retorna uma nova lista com os itens que foram't duplicados/removidos. Isto é o que eu tenho, mas para ser honesto eu não sei o que fazer.

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t
Solução

A abordagem comum para obter uma coleção única de itens é utilizar um set`. Os conjuntos são coleções despedidas de objetos distintos. Para criar um conjunto a partir de qualquer iterável, você pode simplesmente passá-lo para a função embutida set(). Se mais tarde você precisar de uma lista real novamente, você pode passar o conjunto para a função list().

O exemplo seguinte deve cobrir tudo o que você está tentando fazer:

>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]

Como você pode ver no resultado do exemplo, a ordem original não é mantida. Como mencionado acima, os conjuntos são coleções não ordenadas, portanto a ordem é perdida. Ao converter um conjunto de volta para uma lista, é criada uma ordem arbitrária.

Manutenção da ordem

Se o pedido for importante para você, então você terá que usar um mecanismo diferente. Uma solução muito comum para isso é confiar em OrderedDict para manter a ordem das chaves durante a inserção:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

Começando com Python 3.7, o dicionário embutido é garantido para manter a ordem de inserção também, assim você também pode usar isso diretamente se você estiver em Python 3.7 ou posterior (ou CPython 3.6):

>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

Note que isto tem a sobrecarga de criar primeiro um dicionário e depois criar uma lista a partir dele. Se você não precisa realmente preservar a ordem, é melhor usar um conjunto. Verifique esta pergunta para mais detalhes e formas alternativas de preservar a ordem ao remover duplicatas.


Finalmente note que tanto o set como as soluções OrderedDict/dict requerem que os seus itens sejam faticáveis. Isto geralmente significa que eles têm que ser imutáveis. Se você tiver que lidar com itens que não são hashable (por exemplo, listar objetos), então você terá que usar uma abordagem lenta na qual você basicamente terá que comparar cada item com todos os outros itens de um loop aninhado.

Comentários (4)

É uma linha única: list(set(source_list)) irá fazer o truque.

Um set é algo que não pode ter duplicatas.

Atualização: uma abordagem de preservação de ordem é duas linhas:

from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()

Aqui utilizamos o fato de que OrderedDict lembra a ordem de inserção das chaves, e não a altera quando um valor em uma determinada chave é atualizado. Nós inserimos True como valores, mas podemos inserir qualquer coisa, os valores simplesmente não são utilizados. (o set funciona muito como um dict com valores ignorados, também).

Comentários (3)

Se não te importas com a encomenda, faz isto:

def remove_duplicates(l):
    return list(set(l))

Um set é garantido de não ter duplicados.

Comentários (1)