Encontrar duplicados numa lista sem folha de cálculo
Publicado a 07/08/2026 · 11 min de leitura · Ferramentas de texto e idioma
Daniel Okonkwo — Programador front-end e redator de Tecnologia na OneKitly
Desempenho web · Formatos de ficheiro
Verificado a partir de 4 fontes
O duplicate-line-finder compara linhas inteiras, byte a byte. Por omissão a comparação distingue maiúsculas: Paris, paris e PARIS passados juntos não deram duplicado nenhum; ligando «Ignorar maiúsculas» assinala um, impresso como Paris, a grafia da primeira ocorrência. Não apara: «Paris» por cima de «Paris» com um espaço final volta sem duplicados, nos dois modos de caixa. É essa a surpresa mais frequente, e vale a pena saber que a ferramenta irmã remove-duplicate-lines apara sim, por omissão, e nessa mesma entrada de duas linhas apaga uma. Nenhuma das duas está errada; respondem simplesmente a perguntas diferentes, e coexistem no site. Também não aplica normalização Unicode: uma palavra cujo acento cabe num só ponto de código e a mesma palavra cujo acento é uma letra seguida de uma marca combinante são duas linhas diferentes, embora se desenhem igual — o que afeta em especial as listas francesas, espanholas e portuguesas. A saída não é uma lista sem duplicados. É o conjunto de valores que aparecem mais de uma vez, impressos uma vez cada um, pela ordem da primeira aparição e com o texto exato dessa primeira aparição. Se nada se repete, obtém uma mensagem curta em vez de uma caixa vazia. As linhas vazias contam como qualquer outra, com uma esquisitice: se o único valor repetido da sua lista for a linha vazia, a ferramenta anuncia que não há duplicados, porque a saída seria uma string vazia e a string vazia dispara essa mesma mensagem.
Duas linhas que parecem idênticas muitas vezes não são. A caixa, um espaço final, um espaço inquebrável e duas codificações diferentes da mesma letra acentuada foram passados pelo detetor de duplicados, e ele não assinalou nenhum em três dos quatro casos.
O que a ferramenta devolve realmente
Conta cada linha, guarda aquelas cuja contagem passa de um, e imprime cada uma delas uma vez. Sobre a entrada b, a, b, a, c devolveu b e depois a — nessa ordem porque b aparece primeiro, não porque b se repita mais. Nada é ordenado, nada é retirado da sua lista, e o número de repetições de cada valor não é indicado. Se quer a lista sem as repetições, essa é outra ferramenta, o remove-duplicate-lines, e mantém a primeira ocorrência de cada valor na posição original.
O texto que imprime é a primeira ocorrência, palavra por palavra. Parece um detalhe até ligar «Ignorar maiúsculas»: dado Apple, banana, APPLE imprime Apple, nem APPLE nem apple. Decidiu que os dois são o mesmo valor, tem de lhe mostrar um, e mostra o que encontrou primeiro. Se a sua lista mistura grafias gritadas e normais, a saída diz-lhe que grafia chegou primeiro, não qual é a mais frequente nem qual é a correta.
O espaço final, e a ferramenta irmã que discorda
«Paris» por cima de «Paris» com um espaço final não produziu duplicados, e «Paris» por cima de «espaço Paris» também não. As duas linhas diferem num carácter, esse carácter é invisível, e a ferramenta não tem opção de aparar para ligar. Entretanto, o remove-duplicate-lines traz um interruptor «Aparar linhas» ligado de fábrica: entram essas mesmas duas linhas e sai uma. Duas ferramentas da mesma categoria, a uma página de distância, dando respostas opostas sobre a mesma entrada. Ambas se defendem: um detetor de duplicados que aparasse mentiria sobre o que está no seu ficheiro, e um removedor que não aparasse deixaria uma lista que continua a parecer duplicada.
A consequência prática é uma ordem de operações. Passe primeiro o trim-lines pela lista e depois o detetor. Sobre uma entrada deliberadamente desarrumada — dois espaços, alpha, dois espaços, depois uma linha só de tabulação, depois dois espaços, beta, um espaço, depois uma linha vazia, depois alpha — o detetor não assinalou duplicados sobre o texto em bruto, e assinalou alpha sobre esse mesmo texto depois de lhe passar o trim-lines e o remove-blank-lines. Nada na lista mudou de um modo que um leitor notasse. O que mudou foi a capacidade da ferramenta de ver o que o leitor via.
Duas escritas da mesma palavra acentuada
O Unicode pode escrever uma letra acentuada de duas maneiras. Ou como um ponto de código que já carrega o acento, ou como a letra nua seguida de uma marca combinante à parte. Ambas se desenham com o mesmo glifo, ambas estão corretas, e qual delas lhe calha depende da proveniência do texto: alguns sistemas operativos e algumas vias de introdução produzem a forma decomposta por omissão. O anexo padrão Unicode n.º 15 define as formas de normalização que fazem corresponder uma à outra, e o JavaScript expõe-nas através de um método de string. O duplicate-line-finder não o chama.
Assim, uma lista com a palavra «café» escrita uma vez de cada modo voltou sem duplicados. As duas linhas são visualmente indistinguíveis e medem quatro pontos de código contra cinco. Depois a esquisitice: acrescente uma terceira cópia na primeira escrita e a ferramenta assinala de repente um duplicado, porque duas das três coincidem agora exatamente. É essa a forma de falha a vigiar. Não é que a ferramenta nunca encontre duplicados acentuados; é que encontra alguns, o que torna muito mais difícil notar os que lhe escapam. Se a sua lista é francesa, espanhola, portuguesa, alemã ou italiana e as contagens parecem um pouco baixas, é a primeira coisa a testar — e a maneira de testar é ordenar a lista primeiro: as duas escritas ficarão lado a lado e denunciar-se-ão ao recusarem parecer diferentes.
«Ignorar maiúsculas» não é o mesmo que dobrar a língua
O interruptor põe ambos os lados em minúsculas com a correspondência independente da língua que o JavaScript oferece. Isso cobre os casos correntes nas nossas seis línguas, e cobre bem as letras acentuadas: as formas maiúscula e minúscula de uma vogal acentuada dobram-se uma na outra. Não faz nada além do que uma língua concreta desejaria. A forma maiúscula alemã escrita com duas letras e o eszett não se dobram juntos, o que foi verificado: uma lista de duas linhas com a escrita maiúscula e a minúscula de uma palavra alemã corrente voltou sem duplicados, porque pôr em minúsculas a forma gritada dá duas letras onde a outra linha tem uma.
O ponto geral é que «Ignorar maiúsculas» responde a uma pergunta tipográfica, não linguística. Duas linhas que um leitor francês chamaria a mesma entrada — uma com o acento escrito e outra sem — não são duplicados aqui e nunca serão, porque tirar acentos é outra operação com outra ferramenta. Se é essa a comparação de que precisa, tire primeiro os acentos de uma cópia da lista, passe o detetor pela cópia, e use a saída como lista de coisas a verificar no original.
Uma rotina que funciona
Limpar, depois procurar, depois decidir, depois remover. O trim-lines e o remove-blank-lines põem cada linha numa forma comparável. O duplicate-line-finder diz-lhe que valores se repetem, sem tocar em nada. Olha para essa lista curta e decide se cada repetição é uma dupla entrada verdadeira ou duas coisas diferentes que partilham um nome — a ferramenta não pode saber, e é esse o passo que as pessoas saltam. Só então o remove-duplicate-lines passa pelo original. Fazê-lo por esta ordem significa que nunca apaga uma linha que não tenha olhado, o que importa quando a lista são referências de clientes e não dados de teste.
Um último detalhe saído dos ensaios. As duas ferramentas dividem num avanço de linha precedido de um retorno de carro opcional, portanto uma lista guardada no Windows e a mesma guardada no Mac dão resultados idênticos: um ficheiro CRLF com duas cópias da letra a assinalou um duplicado, exatamente como a versão simples. E uma quebra de linha final no fim da sua lista cria uma última linha vazia, que é contada mas, sozinha, nunca é impressa.
| Entrada | O que assinalou | Porquê |
|---|---|---|
| Paris, paris, PARIS — definições por omissão | Sem duplicados | «Ignorar maiúsculas» está desligado por omissão; as três linhas diferem |
| As mesmas três linhas com «Ignorar maiúsculas» | Paris — impresso com a grafia da primeira ocorrência | Ambos os lados são postos em minúsculas para comparar, mas o texto original é guardado para mostrar |
| Paris, depois Paris seguido de um espaço | Sem duplicados, nos dois modos de caixa | A ferramenta nunca apara e não tem opção de aparar |
| As mesmas duas linhas no remove-duplicate-lines | Sai uma só linha | Essa ferramenta tem um interruptor «Aparar linhas» ligado por omissão |
| New York com espaço normal, depois New York com U+00A0 | Sem duplicados | Pontos de código diferentes; a comparação é sobre os carateres exatos |
| A palavra café duas vezes, escrita com as duas formas Unicode | Sem duplicados | Não é aplicada normalização; uma linha tem quatro pontos de código e a outra cinco |
| O mesmo, mais uma terceira cópia na primeira forma | café — é assinalado um duplicado | Duas das três coincidem agora exatamente, portanto a contagem chega a dois |
| Uma lista cujo único valor repetido é a linha vazia | Sem duplicados | A saída seria uma string vazia, e uma saída vazia dispara essa mesma mensagem |
Perguntas frequentes
- O detetor diz que não há duplicados mas eu vejo duas linhas idênticas. O que se passa?
- Três candidatos, por ordem de probabilidade. Um espaço no início ou no fim de uma delas, que a ferramenta não apara. Um espaço inquebrável em vez de um normal algures no interior, o que acontece constantemente em texto colado de documentos. Ou duas escritas Unicode diferentes da mesma letra acentuada. Teste-os por essa ordem: passe o trim-lines pela lista e tente de novo, o que resolve o primeiro candidato em segundos. Se continuar sem encontrar nada e as linhas tiverem acentos, é o terceiro candidato, e ordenar a lista porá as duas escritas lado a lado para as poder comparar.
- Porque é que há ao mesmo tempo um detetor e um removedor de duplicados?
- Porque respondem a perguntas diferentes e têm definições por omissão diferentes. O detetor informa o que se repete e não muda nada, para que olhe antes de cortar; não apara, o que faz dele um relato fiel do que está literalmente no ficheiro. O removedor produz uma lista limpa e apara por omissão, o que o torna tolerante ao lixo invisível que uma colagem traz consigo. Sobre uma lista de duas linhas que só diferem num espaço final, o detetor diz que não há nada a assinalar e o removedor apaga uma. Não é um defeito de nenhum dos dois; é a razão para passar o detetor primeiro quando a lista importa.
- Diz-me quantas vezes cada valor se repete?
- Não. Conta internamente, usa a contagem para decidir se um valor merece ser impresso, e depois imprime só o valor. Sobre b, a, b, a, c devolveu b e a sem número algum, e não há opção para os mostrar. Se precisa das contagens, a via prática é ordenar a lista e ler as séries, ou usar um contador de palavras ou de ocorrências sobre os valores que já sabe repetirem-se. O papel do detetor é dar-lhe uma lista curta de suspeitos, e cinge-se a isso de propósito.
- Vai tratar um endereço de e-mail escrito em duas caixas diferentes como um só endereço?
- Só se ligar «Ignorar maiúsculas», e deve: a metade de domínio de um endereço é insensível a maiúsculas por especificação, portanto a mesma caixa escrita de duas maneiras é realmente um só endereço. Com o interruptor desligado, a ferramenta não assinala nada sobre uma lista de duas linhas com a escrita mista e a minúscula do mesmo endereço, o que foi verificado diretamente. Vale a pena saber antes de tirar duplicados de uma exportação de contactos, porque uma lista que parece limpa com 1 200 linhas pode conter duas dúzias destas, e cada uma é uma pessoa que recebe o envio duas vezes.
- Posso usar isto numa lista de milhares de linhas?
- Sim. O trabalho são uma passagem para contar e outra para recolher, com uma tabela de dispersão indexada pela linha, portanto o tempo cresce mais ou menos ao ritmo do número de linhas e não do seu quadrado — uma comparação ingénua de cada linha contra todas as outras não sobreviveria a alguns milhares de linhas, e não é o que acontece aqui. Tudo corre na página, na sua máquina, sem envio, pelo que o teto prático é a memória do seu navegador e não um limite de servidor. O que o vai atrasar não é a ferramenta: é ler a saída e decidir o que significa cada repetição.
Artigos que podem interessar-lhe
Todos os guias →Ferramentas relacionadas
Tudo o que se segue descreve o que estas ferramentas fazem hoje, verificado executando as suas próprias transformações sobre as entradas exatas reproduzidas em cada artigo, e não o que uma norma obrigue uma ferramenta de texto a fazer. O tratamento do texto linha a linha não tem autoridade única: o que conta como espaço, se duas linhas acentuadas são ou não a mesma linha, e onde termina um URL dentro de uma frase são decididos de forma diferente por cada programa onde colar texto. Quando uma ferramenta erra num caso, isso é dito com franqueza em vez de contornado. Antes de passar qualquer disto por uma lista que não possa reexportar, passe por uma cópia e compare o número de linhas nas duas pontas.
Fontes
Detetaste um erro neste artigo?