Cómo eliminar duplicados de un array con JavaScript

Javascript

En este tutorial vamos a ver cómo puedes eliminar tanto elementos de tipo primitivo duplicados como objetos duplicados de un array con JavaScript, una tarea bastante habitual. Para ello crearemos un nuevo array que contenga todos los elementos de original salvo aquellos que estén repetidos.

Información! Los tipos primitivos de JavaScript son elementos de tipo nativo como por ejemplo números o cadenas de texto. Podemos comparar elementos de tipo primitivo directamente. Sin embargo, cuando queremos eliminar objetos duplicados, tendremos que comparar sus propiedades y, además, el criterio a seguir para considerar que un objeto está duplicado depende del objetivo que se pretende conseguir. Si quieres ver en detalle cuales son , consulta cuál es la diferencia entre objetos y tipos primitivos en JavaScript.
Si no sabes de qué tipo van a ser los elementos de un array, consulta el siguiente tutorial, en donde explico cómo saber de qué tipo es un elemento en JavaScript.

Elimina elementos duplicados

Para lograr eliminar los duplicados podemos usar varios métodos.  A continuación puedes ver algunos de los métodos más utilizados.

Usa un bucle for

El bucle for suele ser la opción escogida cuando se desconocen otros métodos. Su uso es muy sencillo, aunque no es la opción más elegante.

Primero veremos el código para eliminar elementos de tipo primitivo. Luego lo usaremos para crear una función y un método.

Lo que haremos será recorrer el array y agregar cada elemento a un nuevo array siempre y cuando no exista ya en el mismo, para lo cual nos valdremos del método includes:

const numeros = [1, 2, 2, 3, 4, 4, 5];
const unicos = [];

for(var i = 0; i < numeros.length; i++) {
 
  const elemento = numeros[i];
 
  if (!unicos.includes(numeros[i])) {
    unicos.push(elemento);
  }
}

console.log(unicos); // [1, 2, 3, 4, 5]

También podemos crear una función que elimine los elementos duplicados del array mediante un bucle for, de modo que podamos usarla en más ocasiones:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const eliminaDuplicados = (arr) => {
 
  const unicos = [];
 
  for(var i = 0; i < arr.length; i++) {
 
    const elemento = arr[i];
  
    if (!unicos.includes(arr[i])) {
      unicos.push(elemento);
    }
  }
  
  return unicos;
}

console.log(eliminaDuplicados(numeros)); // [1, 2, 3, 4, 5]

Finalmente, también podemos agregar un método al objeto Array de JavaScript usando el método prototype, estando disponible para todos los arrays que creemos:

const numeros = [1, 2, 2, 3, 4, 4, 5];

Array.prototype.unicos = function () {
  const unicos = [];
  for(i = 0; i < this.length; i++) {
    const valor = this[i];
 
    if (unicos.indexOf(valor) < 0) {
      unicos.push(valor);
    }
  }
 
  return unicos;
}

console.log(numeros.unicos()); // [1, 2, 3, 4, 5]

Usa el método filter

El método filter es un método nativo de los arrays en JavaScript. Es una opción más elegante que un bucle, ya que reduce el gran medida el código necesario. El método filter está disponible para todos los arrays de JavaScript.

Este método creará un array con los elementos de nuestro array original que cumplan la condición que especifiquemos. Si el método devuelve true, se agregará el elemento al array resultante. De lo contrario se descartará. La condición se especifica mediante una función que se ejecutará para cada elemento.

Para eliminar los elementos duplicados del array con el método filter usaremos una función como parámetro del mismo que se ejecutará para cada uno de los elementos del array. Esta función acepta como parámetro el valor y el índice del elemento que se está procesando, siendo el propio método filter el que se encarga de ejecutar la función en cada iteración.

En nuestro caso insertaremos cada valor en el nuevo array salvo que un elemento ya haya sido agregado previamente al mismo. Para realizar esta comprobación usamos el método indexOf, que devolverá el índice del primer elemento encontrado con el valor que usemos como parámetro. Si dicho índice coincide con el del elemento actual, devolvemos true. De lo contrario devolvemos false.

const numeros = [1, 2, 2, 3, 4, 4, 5];

const unicos = numeros.filter((valor, indice) => {
    return numeros.indexOf(valor) === indice;
  }
);

console.log(unicos); // [1, 2, 3, 4, 5]

Sin embargo, el método indexOf no es eficiente cuando un array contiene muchos elementos. En su lugar podemos usar una tabla hash, comprobando al instante si un elemento existe o no en el nuevo array en el que insertamos los elementos:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const tabla = {};
const unicos = numeros.filter((indice) => {
  return tabla.hasOwnProperty(indice) ? false : (tabla[indice] = true);
});

console.log(unicos); // [1, 2, 3, 4, 5]

También podríamos crear una función que elimine los elementos duplicados del array usando el método filter, de modo que podamos usarla en más ocasiones:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const eliminaDuplicados = (arr) => {
  return arr.filter((valor, indice) => {
    return arr.indexOf(valor) === indice;
  });
}

console.log(eliminaDuplicados(numeros)); // [1, 2, 3, 4, 5]

Al igual que hemos hecho en el caso del bucle for, también podemos agregar un nuevo método al objeto Array de JavaScript que elimine los elementos duplicados con el método filter. Así estará disponible para todos los arrays que declaremos:

const numeros = [1, 2, 2, 3, 4, 4, 5];

Array.prototype.unicos = function () {
  return this.filter((valor, indice) => {
    return this.indexOf(valor) === indice;
  });
}

console.log(numeros.unicos()); // [1, 2, 3, 4, 5]

Usa una estructura Set

Otro método mediante el que eliminar elementos duplicados consiste en usar la estructura Set de JavaScript ES6, que permite crear conjuntos de valores únicos. Lo primeros que haremos será crear un nuevo conjunto usando nuestro array como parámetro. Cuando se cree el conjunto se eliminarán automáticamente los valores duplicados.

Seguidamente, creamos un nuevo array usando el operador spread de propagación ... que nos permite obtener los elementos del conjunto mediante destructuring.

const numeros = [1, 2, 2, 3, 4, 4, 5];
 
const unicos = [... new Set(numeros)];
 
console.log(unicos); // [1, 2, 3, 4, 5]

Para aquellos a quienes este código les resulte complicado, aquí está otra versión alterantiva:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const conjunto = new Set(numeros);
const unicos = [... conjunto];

console.log(unicos); // [1, 2, 3, 4, 5]

Ahora vamos a crear una función que elimine los elementos duplicados del array haciendo uso del método filter, pudiendo así usarla en más ocasiones:

const numeros = [1, 2, 2, 3, 4, 4, 5];
 
const eliminaDuplicados = (arr) => {
  return [... new Set(arr)];
}
 
console.log(eliminaDuplicados(numeros)); // [1, 2, 3, 4, 5]

Ahora agregaremos un método al objeto Array de JavaScipt que elimine los duplicados usando la estructura Set, estando disponible para todos los arrays. Para ello usaremos el método prototype:

const numeros = [1, 2, 2, 3, 4, 4, 5];

Array.prototype.unicos = function () {
  return [... new Set(this)];
}

console.log(numeros.unicos()); // [1, 2, 3, 4, 5]

Usa un bucle forEach

Si prefieres un método más clásico, siempre puedes usar un bucle forEach, que es un método presente en todos los arrays de JavaScript. El bucle foreach nos permitirá recorrer los elementos del array con una función en la que podemos agregar aquellos elementos que no se repitan a un nuevo array.

En el siguiente ejemplo recorremos el array numeros con un bucle foreach, en el que usamos una función que se ejecutará para cada elemento del array. Vamos a agregar cada elemento a un nuevo array al que llamaremos unicos siempre que no exista ya en el mismo, para lo cual usaremos del método includes:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const unicos = [];

numeros.forEach( (elemento) => {
  if (!unicos.includes(elemento)) {
    unicos.push(elemento);
  }
});

console.log(unicos); // [1, 2, 3, 4, 5]

También podemos crear una función para eliminar los elementos duplicados del array mediante un bucle foreach:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const eliminaDuplicados = (arr) => {

  const unicos = [];
  arr.forEach( (elemento) => {
    if (!unicos.includes(elemento)) {
      unicos.push(elemento);
    }
  });
  
  return unicos;
}

console.log(eliminaDuplicados(numeros)); // [1, 2, 3, 4, 5]

En este otro ejemplo usamos el método prototype de JavaScript para agregar un método al prototipo del objeto Array de JavaScript, de modo que el método que agreguemos esté disponible para todos los arrays:

const numeros = [1, 2, 2, 3, 4, 4, 5];

Array.prototype.unicos = function () {
  const unicos = [];
  this.forEach( (elemento) => {
    if (!unicos.includes(elemento)) {
      unicos.push(elemento);
    }
  });
  
  return unicos;
}

console.log(numeros.unicos()); // [1, 2, 3, 4, 5]

Usa el método reduce

El método reduce itera los elementos del array y ejecuta una función que pasaremos como parámetro con cada uno de ellos. Dicha función acepta como parámetros un acumulador y el elemento actual del array. El valor del acumulador se mantendrá con cada iteración, por lo que es un método que resulta útil para calcular totales. Sin embargo en nuestro caso, el acumulador, que inicialmente estará vacío, será un array en donde almacenaremos los elementos que no se repitan.

En este ejemplo usamos el método reduce con el acumulador accArr, que contendrá los elementos únicos que vayamos agregando. Para comprobar si un valor ya existe en el array accArr, usamos el método indexOf. Si no está, lo insertamos. Para inicializar el array accArr, usamos un array vacío [] como segundo parámetro de la función del método reduce.

const numeros = [1, 2, 2, 3, 4, 4, 5];

const unicos = numeros.reduce( (accArr, valor) => {
  if (accArr.indexOf(valor) < 0) {
    accArr.push(valor);
  }
  return accArr;
}, []);

console.log(unicos); // [1, 2, 3, 4, 5]

A continuación crearemos una función para eliminar los elementos duplicados del array usando el método reduce:

const numeros = [1, 2, 2, 3, 4, 4, 5];

const eliminaDuplicados = (arr) => {
  return numeros.reduce( (accArr, valor) => {
    if (accArr.indexOf(valor) < 0) {
      accArr.push(valor);
    }
    return accArr;
  }, []);
}

console.log(eliminaDuplicados(numeros)); // [1, 2, 3, 4, 5]

A continuación usamos el método prototype para agregar un nuevo método al prototipo del objeto Array de JavaScript. El método que agregaremos, al que llamaremos unicos, estará disponible para todos los arrays que declaremos, eliminando los duplicados cuando así lo deseemos:

const numeros = [1, 2, 2, 3, 4, 4, 5];

Array.prototype.unicos = function () {
  return this.reduce((accArr, valor) => {
    if (accArr.indexOf(valor) < 0) {
      accArr.push(valor);
    }
    return accArr;
  }, []);
}

console.log(numeros.unicos()); // [1, 2, 3, 4, 5]

Usando Underscore JS

Algunas librerías disponen ya de métodos que te permitirán eliminar los elementos duplicados de un array. Un ejemplo de ello es el método _uniq de la librería Underscore JS.

const numeros = [1, 2, 2, 3, 4, 4, 5];

console.log(_uniq(numeros, false));

Además, también podemos ordenar el array resultante si el segundo parámetro de la función _uniq tiene el valor true en lugar de false:

console.log(_uniq(numeros, true));

Elimina objetos duplicados

A continuación vamos a ver diversos métodos que nos permitirán eliminar los objetos duplicados de un array. El proceso de eliminación de objetos implica el acceso a sus propiedades, por lo que el proceso difiere de la eliminación de elementos de tipo primitivo.

Usa la estructura map

El objeto Map se itnrodujo en JavaScript ES6 para guardar pares de clave y valor, guardando también el orden de inserción. Primero usamos un array de arrays como parámetro del objeto Map, para luego convertirlo en pares de clave y valor, siendo la clave el nombre. La clave será la propiedad que hace que el objeto esté repetido, pudiendo así asegurarnos de que no habrá elementos repetidos. Finalmente convertimos de nuevo el objeto en un array:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 52, },
];

let personasMap = personas.map(item=>{
    return [item.nombre,item]
});
var personasMapArr = new Map(personasMap); // Pares de clave y valor

let unicos = [...personasMapArr.values()]; // Conversión a un array

console.log(unicos);
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 }
]
*/

Si queremos que un objeto se considere como repetido cuando todas sus propiedades son iguales, tendremos que usar el siguiente el método JSON.stringify, que convertirá todo el objeto en una cadena de texto que podemos usar como clave de cada elemento de la estructura Map. De este modo, los elementos que difieran en una única propiedad de otros no serán reemplazados:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

let personasMap = personas.map(persona => {
    return [JSON.stringify(persona), persona]
});
let personasMapArr = new Map(personasMap); // Pares de clave y valor

let unicos = [...personasMapArr.values()]; // Conversión a un array

console.log(unicos);
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
  { nombre: "Edu" , edad: 20 },
]
*/

A continuación vamos a ver cómo representar los dos casos que hemos visto como una función.

La siguiente función sirve para eliminar duplicados usando la estructura Map cuando especificamos una propiedad que identifica a los objetos como duplicados. la función debe adaptarse a cada tipo de objeto; no puede usarse como función genérica:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const eliminaPersonasDuplicadas = (arr) => {
  const personasMap = arr.map(persona => {
    return [persona.nombre, persona]
  });

  return [...new Map(personasMap).values()];
}

console.log(eliminaPersonasDuplicadas(personas));
/*
[
  { nombre: "Edu" , edad: 20 },
  { nombre: "Manuel",  edad: 34 },
]
*/

Función que elimina duplicados usando la estructura Map cuando basta que una de las propiedades sea diferente para que el objeto se considere duplicado. Puede usarse como función genérica, ya que es independiente del contenido de los objetos:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const eliminaDuplicados = (arr) => {
  
  const arrMap = arr.map(elemento => {
    return [JSON.stringify(elemento), elemento]
  });

  return [...new Map(arrMap).values()];
}

console.log(eliminaDuplicados(personas));
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
  { nombre: "Edu" , edad: 20 },
]
*/

Usa Setreduce

Vamos a eliminar objetos duplicados usando el método Set, que permite crear conjuntos con claves úncias, eliminando automáticamente los elementos duplicados. En el siguiente ejemplo, un elemento se consdiera duplicado cuando la propiedad nombre es la misma. Para llevar a cabo dicha tarea usaremos el método reduce, en cuyo interior agregaremos los elementos del array al conjunto seObj, cuya clave será la propiedad nombre. De este modo evitamos que se repitan las claves:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const setObj = new Set(); // creamos pares de clave y array

const unicos = personas.reduce((acc, persona) => {
  if (!setObj.has(persona.nombre)){
    setObj.add(persona.nombre, persona)
    acc.push(persona)
  }
  return acc;
},[]);


console.log(unicos);
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
]
*/

En caso de querer que el objeto se considere como repetido cuando todas sus propiedades sean iguales, tendremos que usar el siguiente el método JSON.stringify para transformar todo el objeto en una cadena que usaremos como clave en la estructura Set:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const setObj = new Set(); // creamos pares de clave y array

const unicos = personas.reduce((acc, persona) => {
  const clave = JSON.stringify(persona);
  
  if (!setObj.has(clave)){
    setObj.add(clave, persona)
    acc.push(persona)
  }
  return acc;
},[]);

Veamos ahora cómo representar los dos casos anteriores mediante una función. La función que ves a continuación sirve para eliminar duplicados usando el método reduce y la estructura Set en el caso de que los objetos se consideran duplicados cuando una única propiedad específica se repite. En nuestro ejemplo, dicha propiedad es la propiedad nombre:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const eliminaPersonasDuplicadas = (arr) => {

  const setObj = new Set();

  return personas.reduce((acc, persona) => {
  
    if (!setObj.has(persona.nombre)){
      setObj.add(persona.nombre, persona)
      acc.push(persona)
    }
    return acc;
  },[]);
}

console.log(eliminaPersonasDuplicadas(personas));
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
]
*/

En el siguiente ejemplo, un objeto se considerará duplicado cuando todas sus propiedades sean idénticas. Puede usarse como método genérico de eliminación de objetos duplicados con cualquier array que contanga objetos:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const eliminaDuplicados = (arr) => {

  const setObj = new Set(); // creamos pares de clave y array
  
  return arr.reduce((acc, elemento) => {

    const clave = JSON.stringify(elemento);

    if (!setObj.has(clave)){
      setObj.add(clave, elemento)
      acc.push(elemento)
    }
    return acc;
  },[]);
}

console.log(eliminaDuplicados(personas));
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
  { nombre: "Edu" , edad: 20 },
]
*/

Usa un bucle for

Veamos también cómo duplicados usando un bucle for cuando el array contiene objetos. En el siguiente ejemplo consideramos que una persona está duplicada si su nombre es el mismo. Lo que haremos será recorrer el array personas, agregando cada elemento no duplicado al array unicos. Una persona estará duplicada si ya existe una persona con el mismo nombre en el array unicos, por lo que tendremos que recorrerlo con cada iteración del bucle principal.

Lo lógica es la misma que la que hemos usado para eliminar elementos de tipo primitivo.

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 52, },
];
const unicos = [];

for(var indice = 0; indice < personas.length; indice++) {

  const persona = personas[indice];
  let esDuplicado = false;
  for(var i = 0; i < unicos.length; i++) {

    if (unicos[i].nombre === persona.nombre) {
      esDuplicado = true;
      break;
    }
  }
  
  if (!esDuplicado) {
    unicos.push(persona);
  }
}

console.log(unicos);
/*
[
  { nombre: "Edu", edad: 35, },
  { nombre: "Manuel", edad: 34 }
]
*/

La siguiente función eliminará los objetos de tipo persona duplicados mediante un bucle for:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 52, },
];

const eliminaDuplicados = (arr) => {

  const unicos = [];
  for(var indice = 0; indice < personas.length; indice++) {

    const persona = personas[indice];
    let esDuplicado = false;
    for(var i = 0; i < unicos.length; i++) {

      if (unicos[i].nombre === persona.nombre) {
        esDuplicado = true;
        break;
      }
    }

    if (!esDuplicado) {
      unicos.push(persona);
    }
  }
  
  return unicos;
}

console.log(eliminaDuplicados(personas));
/*
[
  { nombre: "Edu", edad: 35, },
  { nombre: "Manuel", edad: 34 },
]
*/

Usando Underscore JS

Si usas la librería Underscore JS también puedes usar el método _uniq para obtener un array sin duplicados basándote en alguna propiedad del objeto:

const personas = [
  { nombre: 'Edu', edad: 35, },
  { nombre: 'Manuel', edad: 34, },
  { nombre: 'Edu', edad: 20, },
  { nombre: 'Manuel', edad: 34, },
];

const unicos = _.uniq(personas, function(persona){
    return persona.nombre;
});

console.log(unicos);
/*
[
  { nombre: "Edu" , edad: 35 },
  { nombre: "Manuel",  edad: 34 },
  { nombre: "Edu" , edad: 20 },
]
*/

Y esto ha sido todo.


Avatar de Edu Lazaro

Edu Lázaro: Ingeniero técnico en informática, actualmente trabajo como desarrollador web y programador de videojuegos.

👋 Hola! Soy Edu, me encanta crear cosas y he redactado esta guía. Si te ha resultado útil, el mayor favor que me podrías hacer es el de compatirla en Twitter 😊

Si quieres conocer mis proyectos, sígueme en Twitter.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *