Como posso encontrar as duplicatas em uma lista Python e criar outra lista das duplicatas? A lista contém apenas números inteiros.
python
list
duplicates
MFB
fonte
fonte
Respostas:
Para remover duplicatas, use
set(a)
. Para imprimir duplicatas, algo como:Observe que
Counter
não é particularmente eficiente ( tempos ) e provavelmente é um exagero aqui.set
terá um desempenho melhor. Este código calcula uma lista de elementos exclusivos na ordem de origem:ou, mais concisamente:
Eu não recomendo o último estilo, porque não é óbvio o que
not seen.add(x)
está fazendo (oadd()
método set sempre retornaNone
, daí a necessidadenot
).Para calcular a lista de elementos duplicados sem bibliotecas:
Se os elementos da lista não forem hasháveis, você não poderá usar sets / dicts e precisará recorrer a uma solução de tempo quadrático (compare cada um com cada um). Por exemplo:
fonte
O(n)
, porque apenas itera a lista uma vez e as pesquisas definidas sãoO(1)
.dup = []
else: dup.append(x)
print()
seen = set()
entãodupe = set(x for x in a if x in seen or seen.add(x))
fonte
l
porset(l)
apenas reduz a complexidade do pior momento e, portanto, não faz nada para resolver as preocupações de eficiência em larga escala com esta resposta. Provavelmente não era tão simples, afinal. Em suma, não faça isso.Você não precisa da contagem, apenas se o item foi visto antes. Adaptado que responde a este problema:
Caso a velocidade seja importante, aqui estão alguns horários:
Aqui estão os resultados: (bem feito @JohnLaRooy!)
Curiosamente, além dos horários, o ranking também muda levemente quando o pypy é usado. O mais interessante é que a abordagem baseada em contador se beneficia enormemente das otimizações do pypy, enquanto a abordagem de cache do método que sugeri parece não ter quase nenhum efeito.
Aparentemente, esse efeito está relacionado à "duplicidade" dos dados de entrada. Eu configurei
l = [random.randrange(1000000) for i in xrange(10000)]
e obtive estes resultados:fonte
add
toda vez que uma inserção fosse necessária.pypy
se você tiver à mão e estiver indo para a velocidade.Você pode usar
iteration_utilities.duplicates
:ou se você deseja apenas uma duplicata, isso pode ser combinado com
iteration_utilities.unique_everseen
:Ele também pode lidar com elementos laváveis (no entanto, ao custo de desempenho):
Isso é algo que apenas algumas das outras abordagens aqui podem lidar.
Benchmarks
Fiz um rápido benchmark contendo a maioria (mas não todas) das abordagens mencionadas aqui.
A primeira referência incluiu apenas um pequeno intervalo de comprimentos de lista, porque algumas abordagens têm
O(n**2)
comportamento.Nos gráficos, o eixo y representa o tempo, portanto, um valor mais baixo significa melhor. Também é plotado log-log para que a ampla gama de valores possa ser melhor visualizada:
Removendo as
O(n**2)
abordagens, fiz outro benchmark de até meio milhão de elementos em uma lista:Como você pode ver, a
iteration_utilities.duplicates
abordagem é mais rápida do que qualquer uma das outras abordagens e até o encadeamentounique_everseen(duplicates(...))
foi mais rápido ou igualmente rápido do que as outras abordagens.Outra coisa interessante a ser observada aqui é que as abordagens dos pandas são muito lentas para listas pequenas, mas podem competir facilmente por listas mais longas.
No entanto, como esses benchmarks mostram que a maioria das abordagens tem desempenho aproximadamente igual, não importa muito qual delas é usada (exceto as três que tiveram
O(n**2)
tempo de execução).Referência 1
Referência 2
aviso Legal
1 Esta é a partir de uma biblioteca de terceiros que tenho escrito:
iteration_utilities
.fonte
Eu me deparei com essa pergunta enquanto olhava para algo relacionado - e me pergunto por que ninguém ofereceu uma solução baseada em gerador? Resolver esse problema seria:
Eu estava preocupado com a escalabilidade, então testei várias abordagens, incluindo itens ingênuos que funcionam bem em pequenas listas, mas escalam horrivelmente à medida que as listas ficam maiores (nota: seria melhor usar o tempo, mas isso é ilustrativo).
Eu incluí o @moooeeeep para comparação (é impressionantemente rápido: mais rápido se a lista de entradas for completamente aleatória) e uma abordagem de iterais que é ainda mais rápida para as listas classificadas ... Agora inclui a abordagem de pandas do @firelynx - lenta, mas não terrivelmente e simples. Nota - a abordagem de ordenação / tee / zip é consistentemente mais rápida na minha máquina para listas grandes e ordenadas, o moooeeeep é mais rápido para listas embaralhadas, mas sua milhagem pode variar.
Vantagens
Premissas
Solução mais rápida, 1 milhão de entradas:
Abordagens testadas
Os resultados para o teste 'todos os enganados' foram consistentes, encontrando duplicatas "primeiro" e depois duplicatas "todos" nesta matriz:
Quando as listas são embaralhadas primeiro, o preço do tipo se torna aparente - a eficiência cai visivelmente e a abordagem @moooeeeep domina, com as abordagens set & dict sendo semelhantes, mas com desempenho inferior:
fonte
random.shuffle(c)
dar conta disso. Além disso, também não consigo replicar seus resultados ao executar o script inalterado (ordenação totalmente diferente), talvez também seja dependente da CPU.Usando pandas:
fonte
O contador é novo no python 2.7:
Em uma versão anterior, você pode usar um ditado convencional:
fonte
Aqui está uma solução pura e concisa -
fonte
Sem converter para lista e provavelmente a maneira mais simples seria algo como abaixo. Isso pode ser útil durante uma entrevista quando eles pedem para não usar conjuntos
======= else para obter 2 listas separadas de valores exclusivos e valores duplicados
fonte
Eu faria isso com os pandas, porque eu uso muito os pandas
Dá
Provavelmente não é muito eficiente, mas com certeza é menos código do que muitas outras respostas, então pensei em contribuir
fonte
pda = pd.Series(a)
print list(pda[pda.duplicated()])
o terceiro exemplo da resposta aceita fornece uma resposta incorreta e não tenta fornecer duplicatas. Aqui está a versão correta:
fonte
Que tal simplesmente percorrer cada elemento da lista, verificando o número de ocorrências e adicionando-as a um conjunto que imprimirá as duplicatas. Espero que isto seja útil a alguém.
fonte
Podemos usar
itertools.groupby
para encontrar todos os itens que possuem dups:A saída será:
fonte
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Eu acho que a maneira mais eficaz de encontrar duplicatas em uma lista é:
Ele usa
Counter
todos os elementos e todos os elementos exclusivos. Subtrair o primeiro pelo segundo deixará de fora apenas as duplicatas.fonte
Um pouco tarde, mas talvez seja útil para alguns. Para uma lista ampla, achei que isso funcionou para mim.
Mostra apenas e todas as duplicatas e preserva a ordem.
fonte
Uma maneira muito simples e rápida de encontrar enganos com uma iteração no Python é:
A saída será a seguinte:
Isso e muito mais no meu blog http://www.howtoprogramwithpython.com
fonte
Estou entrando muito tarde nessa discussão. Mesmo assim, eu gostaria de lidar com esse problema com um liners. Porque esse é o charme do Python. se apenas queremos obter as duplicatas em uma lista separada (ou em qualquer coleção), sugiro que faça o seguinte: diga que temos uma lista duplicada que podemos chamar de 'destino'
Agora, se quisermos obter as duplicatas, podemos usar o liner a seguir:
Este código colocará os registros duplicados como chave e contará como valor no dicionário 'duplicatas'. O dicionário 'duplicado' terá a seguinte aparência:
Se você deseja apenas todos os registros com duplicatas sozinhos em uma lista, é novamente um código muito menor:
A saída será:
Funciona perfeitamente nas versões python 2.7.x +
fonte
Python 3.8 one-liner, se você não quiser escrever seu próprio algoritmo ou usar bibliotecas:
Imprime item e conta:
groupby
utiliza uma função de agrupamento para que você possa definir seus agrupamentos de maneiras diferentes e retornarTuple
campos conforme necessário.groupby
é preguiçoso, por isso não deve ser muito lento.fonte
Alguns outros testes. Claro que fazer ...
... é muito caro. É cerca de 500 vezes mais rápido (a matriz mais longa fornece melhores resultados) para usar o próximo método final:
Apenas 2 loops, sem
l.count()
operações muito caras .Aqui está um código para comparar os métodos, por exemplo. O código está abaixo, aqui está a saída:
O código de teste:
fonte
Método 1:
Explicação: [val para idx, val in enumerate (input_list) se val em input_list [idx + 1:]] é uma compreensão de lista, que retorna um elemento, se o mesmo elemento estiver presente em sua posição atual, na lista, o índice .
Exemplo: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
começando com o primeiro elemento da lista, 42, com o índice 0, verifica se o elemento 42 está presente na input_list [1:] (ou seja, do índice 1 até o final da lista) Como 42 está presente na input_list [1:] , retornará 42.
Em seguida, ele passa para o próximo elemento 31, com o índice 1, e verifica se o elemento 31 está presente na input_list [2:] (ou seja, do índice 2 até o final da lista), porque 31 está presente na input_list [2:], retornará 31.
Da mesma forma, ele percorre todos os elementos da lista e retornará apenas os elementos repetidos / duplicados para uma lista.
Então, porque temos duplicados, em uma lista, precisamos escolher um de cada duplicado, ou seja, remover duplicado entre duplicados e, para fazer isso, chamamos um python interno incorporado chamado set (), e ele remove os duplicados,
Ficamos com um conjunto, mas não uma lista, e, portanto, para converter de um conjunto em lista, usamos tipecasting, list () e isso converte o conjunto de elementos em uma lista.
Método 2:
Explicação: Aqui Criamos duas listas vazias, para começar. Continue percorrendo todos os elementos da lista, para ver se existe em temp_list (inicialmente vazio). Se não estiver na lista_ temp, então a adicionamos à lista_ temp, usando o método append .
Se ele já existe no temp_list, significa que o elemento atual da lista é duplicado e, portanto, precisamos adicioná-lo ao dupe_list usando o método append .
fonte
Basicamente, você remove duplicatas convertendo para set (
clean_list
) e itera o arquivoraw_list
, enquanto remove cada umitem
da lista limpa para ocorrência emraw_list
. Seitem
não for encontrado, aValueError
exceção levantada é capturada e aitem
é adicionada àduplicated_items
lista.Se o índice de itens duplicados for necessário, apenas
enumerate
a lista e brinque com o índice. (for index, item in enumerate(raw_list):
), que é mais rápido e otimizado para listas grandes (como milhares de elementos)fonte
uso do
list.count()
método na lista para descobrir os elementos duplicados de uma determinada listafonte
uma linha, por diversão, e onde uma única declaração é necessária.
fonte
fonte
Solução de uma linha:
fonte
Há muitas respostas aqui em cima, mas acho que essa é uma abordagem relativamente legível e fácil de entender:
Notas:
fonte
Aqui está um gerador rápido que usa um dict para armazenar cada elemento como uma chave com um valor booleano para verificar se o item duplicado já foi produzido.
Para listas com todos os elementos que são tipos hash:
Para listas que podem conter listas:
fonte
fonte
Ao usar o toolz :
fonte
foi assim que tive que fazer isso porque me desafiei a não usar outros métodos:
para que sua amostra funcione como:
fonte
duplist = list(set(a))
.