Array duplicado: por qué esta tarea reunió miles de visitas en Stack Overflow
\n\nImagine: está escribiendo una tienda en línea, el usuario añade productos al carrito. Pero por error o debido a un bug, el mismo iPhone aparece en la lista tres veces. O está parseando una lista de etiquetas de una base de datos, y "JavaScript" aparece 15 veces seguidas. ¿Qué hacer? Correcto — dejar solo los valores únicos.
\n\nLa pregunta "Get all unique values in a JavaScript array (remove duplicates)" en Stack Overflow ha reunido cientos de miles de visitas. Y no es casualidad. La tarea parece simple, pero bajo el capó se esconde todo un arsenal de enfoques: desde soluciones de una línea en el moderno ES6 hasta trucos ingeniosos con filter e indexOf. En este artículo no solo daremos soluciones listas, sino que analizaremos cómo funciona cada una a nivel del motor de JavaScript.
¿Listo para mirar bajo el capó? ¡Vamos allá!
\n\n\n\n
Método n.º 1: Set — el rey del rendimiento
\n\nLa forma más elegante y rápida de obtener valores únicos en un array de JavaScript es usar el objeto Set. Apareció en ES6 y está literalmente creado para esta tarea.
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = [...new Set(numbers)];\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]\n\n¿Cómo funciona bajo el capó?
\nEl objeto Set almacena solo valores únicos. Cuando pasamos un array al constructor new Set(numbers), el motor de JavaScript recorre cada elemento y lo añade a una tabla hash interna. Si el valor ya existe, se ignora. Luego, el operador de propagación ... convierte el Set de vuelta a un array.
¿Por qué es rápido? Porque la búsqueda e inserción en Set se realizan en O(1) (tiempo constante). Para un array de 10 000 elementos, la diferencia con otros métodos será enorme.
\n\nImportante: Set conserva el orden de los elementos, pero solo funciona con primitivos (números, cadenas, valores booleanos). Para objetos, la comparación es por referencia, no por contenido.
\n\n¿Cuándo usarlo?
\n- \n
- Si el array está compuesto por números o cadenas. \n
- Si la velocidad de procesamiento de arrays grandes es importante. \n
- Si escribe código moderno y no le teme a ES6. \n
\n\n
Método n.º 2: filter + indexOf — el clásico del género
\n\nEste método es un veterano de JavaScript. Funciona en todos los navegadores sin polyfills y sigue siendo popular en Stack Overflow.
\n\nconst numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.filter((value, index, arr) => {\n return arr.indexOf(value) === index;\n});\n\nconsole.log(uniqueNumbers); // [1, 2, 3, 4, 5]\n\nAnálisis de la lógica
\nEl método filter crea un nuevo array, dejando solo aquellos elementos para los que el callback devuelve true. Dentro del callback comprobamos: ¿es el índice actual la primera aparición de este valor en el array? Si es así, conservamos el elemento. Si el valor ya apareció antes, indexOf devolverá un índice menor, la condición no se cumplirá y el duplicado será descartado.
La trampa: indexOf recorre el array desde el principio cada vez. Esto da una complejidad de O(n²). Para arrays pequeños (hasta 1000 elementos) la diferencia es imperceptible, pero con 100 000 elementos el navegador podría congelarse por un segundo.
¿Cuándo usarlo?
\n- \n
- Si necesita soportar navegadores antiguos (IE11). \n
- Si el array es pequeño. \n
- Si quiere mostrar claramente la lógica de la "primera aparición". \n
\n\n
Método n.º 3: reduce + acumulador — flexibilidad y control
\n\nEl método reduce da control total sobre el proceso. Nosotros decidimos cómo recopilar el resultado.
const numbers = [1, 2, 2, 3, 4, 4, 5];\nconst uniqueNumbers = numbers.reduce((acc, value) => {\n if (!acc.includes(value)) {\n acc.push