Cómo eliminar duplicados de un array en JavaScript?
La manera más rápida, transformar el array en un Set
y luego volver a un array
Multitud de veces necesitaremos eliminar duplicados de un array
, y sorprendentemente no tenemos una función específica para eso
Pero no todo está perdido, vamos a ver las distintas estrategias que tenemos con las diferentes estructuras de datos
Arrays y Objects
En un array
no tenemos problemas en almacenar duplicados
// definimos el array
const myArr = []
myArr[0] = '😎'
myArr[1] = '😎'
myArr[2] = '😎'
// lo mismo, pero de forma más concisa
const myArr = ['😎', '😎', '😎']
// lo mismo, más compacto si tuviésemos que definir 10 o 20 elementos
const myArr = Array.from({ length: 3 }, () => '😎')
Si en nuestros datos hay duplicados, un array
los almacenará sin problemas
Esto, sin embargo, no pasa con un object
const myObj = { url: '😎', url: '😎', url: '😎' }
console.log(myObj) // {url: '😎'}
En este caso no hemos almacenado ningún duplicado, sólo una copia del mismo valor
Esto lo podemos aprovechar para eliminar duplicados de un array
, aunque el código no es demasiado elegante
const myArr = ['😎', '😎', '😎', '😅'] // tenemos duplicados!
const newArr = []
const myObj = {}
myArr.forEach(el => {
// comprobamos si el valor existe en el objeto
if (!(el in myObj)) {
// si no existe creamos ese valor y lo añadimos al array final, y si sí existe no lo añadimos
myObj[el] = true
newArr.push(el)
}
})
console.log(myArr) // ["😎", "😎", "😎", "😅"]
console.log(newArr) // ["😎", "😅"]
Conseguido, hemos eliminado los duplicados, y en verdad podemos compactar más el código
const myArr = ['😎', '😎', '😎', '😅'] // tenemos duplicados!
const newArr = []
const myObj = {}
myArr.forEach(el => !(el in myObj) && (myObj[el] = true) && newArr.push(el))
console.log(myArr) // ["😎", "😎", "😎", "😅"]
console.log(newArr) // ["😎", "😅"]
Esta solución funciona, pero es ofuscada y algo complicada de leer la primera vez
Sets
Los sets
son como los arrays
pero con características de los object
, y lo que nos interesa aquí es que NO pueden tener duplicados
const myArr = ['😎', '😎', '😎', '😅'] // tenemos duplicados!
const newArr = Array.from(new Set(myArr)) // con Array.from
const newArr2 = [...new Set(myArr)] // con el spread operator
console.log(myArr)
console.log(newArr)
console.log(newArr2)
/*
["😎", "😎", "😎", "😅"]
["😎", "😅"]
["😎", "😅"]
*/
Lo que hacemos es crear un array
utilizando un set
de intermediario, sirve perfectamente
Filter
Otra opción es "filtrar" el array y quedarnos sólo con elementos únicos, con la función filter()
const myArr = ['😎', '😎', '😎', '😅']
const newArr = myArr.filter((el, index) => myArr.indexOf(el) === index)
console.log(myArr)
console.log(newArr)
/*
["😎", "😎", "😎", "😅"]
["😎", "😅"]
*/
Es algo más ofuscado que el set
de antes, pero no tanto como las primeras opciones
Con indexOf
recuperamos el primer índice de ese elemento del array, es decir, tendremos para el array unos números de [0, 0, 0, 3]
Y con la comparación con indexOf(el) === index
tendríamos [0 === 0, 0 === 1, 0 === 2, 3 === 3]
con lo que sólo en el primer y último elemento recibiríamos un true
y por lo tanto el filter
devolvería sólo ese valor, eliminando por lo tanto los duplicados
Reduce
Y también tenemos el reduce
, una función ofuscada por naturaleza pero increiblemente potente
const myArr = ['😎', '😎', '😎', '😅']
const newArr = myArr.reduce((newTempArr, el) => (newTempArr.includes(el) ? newTempArr : [...newTempArr, el]), [])
console.log(myArr)
console.log(newArr)
/*
["😎", "😎", "😎", "😅"]
["😎", "😅"]
*/
Con reduce
empezamos con un array vacío y lo vamos llenando de valores siempre que no estén incluidos en el array original, lo que lo vemos con .includes()
Perfectamente válido, pero terrible para leer si no tienes acostumbrada la vista
Lista de correo: escribo algo de tanto en cuanto