Remoção de duplicatas de um array em JavaScript: análise detalhada

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

De onde vêm as duplicatas e por que isso é um problema?

\n

Imagine: você está coletando dados de uma API, analisando um arquivo CSV ou processando a entrada do usuário. Em 90% dos casos, você encontrará arrays onde o mesmo elemento aparece várias vezes. Isso não é apenas um problema estético — duplicatas podem distorcer estatísticas, quebrar a renderização de listas ou levar a loops infinitos em algoritmos.

\n

A pergunta "Remove duplicate values from a JavaScript array" no Stack Overflow acumulou milhares de visualizações por um bom motivo. Esta é uma operação básica, mas criticamente importante, que todo desenvolvedor deve conhecer. Hoje vamos analisar detalhadamente como diferentes abordagens funcionam — desde as mais ingênuas até as mais eficientes.

\n\n

Método nº1: Set — o mais elegante e rápido

\n

Se você perguntar a um desenvolvedor JavaScript moderno: "Como remover duplicatas?", a primeira coisa que ele dirá é Set. E isso está correto. Mas como funciona?

\n\n
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = [...new Set(numbers)];\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]
\n\n

O que acontece internamente no Set?

\n

O objeto Set armazena valores únicos de qualquer tipo. Quando você passa um array para o construtor new Set(numbers), o motor JavaScript (V8, SpiderMonkey, etc.) executa os seguintes passos:

\n
    \n
  • Iteração pelo array: o motor percorre cada elemento do array original.
  • \n
  • Verificação de unicidade: para cada elemento, uma função hash interna é chamada. Se o elemento já existe no "bucket", ele é ignorado. Se não, é adicionado.
  • \n
  • Montagem do resultado: o operador [...set] (spread) expande o objeto iterável Set de volta para um array.
  • \n
\n

Uma nuance importante: o Set usa o algoritmo de comparação SameValueZero. Isso significa que NaN é considerado igual a NaN (ao contrário de ===), e +0 e -0 são considerados valores diferentes. Na prática, isso raramente importa, mas é bom saber.

\n\n

Desempenho do Set

\n

A complexidade da operação é O(n). Cada elemento é verificado exatamente uma vez. Este é o melhor desempenho entre todos os métodos. Para arrays com 10.000 elementos, a diferença entre Set e outros métodos pode chegar a dezenas de milissegundos — crítico para aplicações de alta carga.

\n\n

Método nº2: filter + indexOf — o clássico

\n

Antes do ES6 (2015), os desenvolvedores usavam a combinação de filter e indexOf. Este método ainda é encontrado em código legado:

\n\n
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.filter((value, index, self) => {\n    return self.indexOf(value) === index;\n});\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]
\n\n

Como funciona?

\n
    \n
  • filter percorre cada elemento do array.
  • \n
  • Para cada elemento, indexOf(value) é chamado, retornando o primeiro índice onde esse valor aparece.
  • \n
  • Se o índice atual do elemento coincide com o primeiro encontrado — significa que é a primeira ocorrência, e o elemento é mantido. Se não coincide — é uma duplicata e é descartado.
  • \n
\n\n

Armadilhas

\n

O principal problema é o desempenho. indexOf internamente usa busca linear (O(n) para cada chamada). Como resultado, para um array de N elementos, a complexidade se torna O(n²). Com 1000 elementos ainda é tolerável, mas com 100.000, a lentidão se torna perceptível.

\n

Outra desvantagem: indexOf não funciona corretamente com NaN. Se o array contiver NaN, indexOf(NaN) sempre retornará -1, e o elemento será adicionado novamente. Para verificar NaN, é necessário usar

Blogs

Book Recommendations