Array Unique: eliminar valores duplicados de un array en Javascript

24 Jun 2011

En Javascript, como en todos los lenguajes de programación, es frecuente trabajar con arrays donde a veces los valores se van rellenando de forma dinámica. En estos casos, es probable que terminemos manejando matrices con múltiples datos duplicados que conviene limpiar antes de operar con ellas eficientemente.

Desgraciadamente, Javascript no tiene un método nativo para optimizar este tipo de objetos por lo que tenemos que crearlo nosotros mismos.

En una línea similar a la del último post ‘Javascript Extremo: cómo salvar algunos bytes en nuestro código‘, @webreflection ha conseguido reducir una de las muchas formas de conseguir esta funcionalidad a sólo 121 bytes. Un código que puede considerarse perfecto por el uso que hace del lenguaje y que no he podido resistirme a compartir aquí:

Array.prototype.unique=function(a){
  return function(){return this.filter(a)}}(function(a,b,c){return c.indexOf(a,b+1)<0
});

Y ahí lo tenemos. Un nuevo método que funciona exactamente como se espera:

var myArr = [ 1, 2, 3, 'foo', 'bar', 'Hello World', 2, 3, 'bar', 1, 4, 5];
console.log( myArr.unique() ); // ["foo", "Hello World", 2, 3, "bar", 1, 4, 5]

El resultado que obtenemos es un array cuyos valores duplicados han sido eliminados. Rápido, limpio y preciso.

Códigos como este son los que me reafirman en eso que llevo defendiendo desde hace años: que los lenguajes de programación no son buenos o malos por si mismos, sino que es el uso que hacemos de ellos lo que determinan un buen o mal resultado.

Más:

{12} Comentarios.

  1. guzman

    a ver si he entendido como funciona esto
    con «Array.prototype.unique» añadimos al prototipo de array una nueva funcion unique

    esta funcion espera un parametro «a» y llama a la funcion «filter» de array
    la funcion filter() de los array crea un nuevo array, con todos los elementos que cumplen ciertos requisitos

    los requisitos se indican con una funcion que se pasa como parametro a filter
    osea «array.filter(funcion_que_dice_si_un_elemento_va_a_estar_en_el_array_devuelto)»
    // para mas detalles
    //http://www.tutorialspoint.com/javascript/array_filter.htm

    asi que cuando escribamos «myArr.unique() » se llama a:

    function(a){
      return function(){
    	return this.filter(a)
    	}
    }
    

    con esto claro viene la segunda parte,

    despues de la defincion de la funcion hay unos parentesis por lo que la funcion es auto ejecutable
    asi que se añade ella sola al prototipo

    (
    function(a,b,c){
    	return c.indexOf(a,b+1)<0
    }
    );
    

    por ultimo:

    como parametro se manda una funcion

    function(a,b,c){
    	return c.indexOf(a,b+1)<0
    }
    

    que es la que espera el metodo filter, como siempre nos hacen trampa estos del javascript y la funcion filter espera tres parametros que si no nos dicen lo que significa cada uno nos va a parecer chino, pero si nos dicen: filter(element, index, array) pues esta mas claro

    asi que la funcion lo que hace es mira a ver si en el array que estoy construyendo ya esta el elemento siguiente

    c= array que estoy construyendo
    a= elemento que estoy mirando a ver si lo añado
    b= indice del elemento
    indexOf = el elemento esta en el array
    <0 = el indexOf devuelve -1 si el elemento no esta

    convertido a cristiano:

    function(elemento_a_mirar_si_añado_al_array,indice_del_elemeno_que_estoy_mirando,array_con_los_elementos_ya_añadidos){
      return array_con_los_elementos_ya_añadidos.indexOf(
        elemento_a_mirar_si_añado_al_array,
        indice_del_elemeno_que_estoy_mirando+1
      )<0
    }
    
    • Carlos Benítez

      Excelente 🙂

      Como vemos, exprimimos las posibilidades del lenguaje con unos pocos bytes para conseguir un código perfectamente funcional.

      Gracias por el análisis Guzmán 😉

  2. Eduardo

    No entiendo algo, si unique=function(a){ } es equivalente a: function unique(a){ }? esto por un lado.
    Por otro en que momento se le pasa el argumento «a» en myArr.unique() ?? no deberia ser myArr.unique(alguna_variable) ??

  3. Alans

    Muy bueno!!! funciona a la perfección. Gracias

  4. Bryan Horna

    ¡Hola Carlos! Primero que nada, felicitarte el código. Es el más pequeño que encontré de todos. Con la explicación de Guzmán quedó claro todo. Ahora, ¿qué hay acerca de la compatibilidad en los navegadores? ¿Crees que funcione en todos los que se use o se necesitaría un polyfill para Array.prototype.filter?
    De antemano gracias por tu respuesta 🙂

  5. Jessrom

    Excelente!! Me fue de gran utilidad, te lo agradezco mucho Carlos, y también gracias a Guzman por su explicación para Dummies :D.

    En cuanto a la compatibilidad de los navegadores sólo existen problemas (como siempre) con nuestro peor enemigo Internet Explorer, especialmente para las versiones IE7 e IE8. Esto se puede comprobar aquí: http://kangax.github.io/es5-compat-table/

    Saludos desde Colombia.

  6. Leonardo

    Este código servirá para usarse en cualquier navegador???

  7. KEVIN ALVAREZ

    ME SALVASTE LA VIDA =)

  8. Aldo AC

    Excelente aporte me ha servido, gracias por compartirlo.

  9. Darwin

    Soy nuevo como programador web, gracias por el aporte de verdad que esta funcion es bien potente cosas como estas hacen que la programacion sea increible

  10. CARLOS ACOSTA

    Muchas gracias, aunque no se porque no me funcionaba, me funciono con jquery: jQuery.unique(array);
    tomado de: http://www.elclubdelprogramador.com/2013/10/29/snippets-elimina-elementos-duplicados-con-jquery/

  11. Fabian Chinchilla

    Por alguna razon me da problemas en AngularJs, en concreto al recorrer una array con un for, me devulve la funcion unique del prototipo de array, en lugar del elemento del array.

    Pero aparte de eso esta excelente lo comprimida que esta la funcion y su funcionamiento

Deja un comentario

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