Eliminación de duplicados de un array en JavaScript: análisis bajo el capó

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿De dónde vienen los duplicados y por qué son un problema?

\n

Imagina: estás recopilando datos de una API, analizando un archivo CSV o procesando la entrada del usuario. En el 90% de los casos, te encuentras con arrays en los que el mismo elemento aparece varias veces. Esto no es solo un problema estético: los duplicados pueden distorsionar las estadísticas, romper el renderizado de listas o provocar bucles infinitos en los algoritmos.

\n

La pregunta "Remove duplicate values from a JavaScript array" en Stack Overflow ha acumulado miles de visitas por una buena razón. Es una operación básica pero críticamente importante que todo desarrollador debe conocer. Hoy miraremos bajo el capó y analizaremos cómo funcionan diferentes enfoques, desde los más ingenuos hasta los más eficientes.

\n\n

Método n.º 1: Set — el más elegante y rápido

\n

Si le preguntas a un desarrollador JavaScript moderno: "¿Cómo eliminar duplicados?", lo primero que dirá es Set. Y es correcto. Pero, ¿cómo 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

¿Qué sucede bajo el capó de Set?

\n

El objeto Set almacena valores únicos de cualquier tipo. Cuando pasas un array al constructor new Set(numbers), el motor de JavaScript (V8, SpiderMonkey, etc.) realiza los siguientes pasos:

\n
    \n
  • Iteración sobre el array: el motor recorre cada elemento del array original.
  • \n
  • Verificación de unicidad: para cada elemento se llama a una función hash interna. Si el elemento ya está en el "cubo" (bucket), se ignora. Si no, se añade.
  • \n
  • Ensamblaje del resultado: el operador [...set] (spread) expande el objeto iterable Set de vuelta a un array.
  • \n
\n

Un detalle importante: Set utiliza el algoritmo de comparación SameValueZero. Esto significa que NaN se considera igual a NaN (a diferencia de ===), mientras que +0 y -0 se consideran valores diferentes. En la práctica, esto rara vez importa, pero es bueno saberlo.

\n\n

Rendimiento de Set

\n

La complejidad de la operación es O(n). Cada elemento se verifica exactamente una vez. Este es el mejor indicador entre todos los métodos. Para arrays de 10 000 elementos, la diferencia entre Set y otros métodos puede ser de decenas de milisegundos, algo crítico para aplicaciones de alta carga.

\n\n

Método n.º 2: filter + indexOf — el clásico del género

\n

Antes de la llegada de ES6 (2015), los desarrolladores usaban la combinación de filter e indexOf. Este método todavía se encuentra en código heredado:

\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

¿Cómo funciona?

\n
    \n
  • filter recorre cada elemento del array.
  • \n
  • Para cada elemento se llama a indexOf(value), que devuelve el primer índice donde aparece ese valor.
  • \n
  • Si el índice actual del elemento coincide con el primero encontrado, significa que es la primera aparición y el elemento se conserva. Si no coincide, es un duplicado y se descarta.
  • \n
\n\n

Inconvenientes

\n

El principal problema es el rendimiento. indexOf internamente utiliza una búsqueda lineal (O(n) por cada llamada). Como resultado, para un array de N elementos, la complejidad se convierte en O(n²). Con 1000 elementos aún es tolerable, pero con 100 000, la ralentización se vuelve notable.

\n

Otra desventaja: indexOf no funciona correctamente con NaN. Si el array contiene NaN, indexOf(NaN) siempre devolverá -1, y el elemento se añadirá repetidamente. Para verificar NaN se necesita usar

Blogs

Book Recommendations