979 votos

Eliminar duplicados de matriz JavaScript

Esto parece como una simple necesidad, pero me he gastado una cantidad excesiva de tiempo tratando de hacerlo en vano. He mirado en otras preguntas y no he encontrado lo que necesito. Tengo una muy simple array de JavaScript como peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"); que puede o no puede contener duplicados y necesito simplemente eliminar los duplicados y poner los valores únicos de una nueva matriz. Eso es todo. Yo podría señalar a todos los códigos que he probado pero creo que es inútil porque no trabajan. Si alguien ha hecho esto y me puede ayudar realmente lo apreciaría. JavaScript o jQuery soluciones son aceptables.

Relacionados con: la manera más Fácil de buscar valores duplicados en un array de JavaScript

2487voto

georg Puntos 52691

"Inteligente" pero ingenuo

uniqueArray = myArray.filter(function(item, pos) {
    return myArray.indexOf(item) == pos;
})

Básicamente, podemos iterar a través de la matriz y, para cada elemento, compruebe si la primera posición de este elemento de la matriz es igual a la posición actual. Obviamente, estas dos posiciones son diferentes para los elementos duplicados.

El uso de la 3ª ("la matriz") parámetro del filtro de devolución de llamada podemos evitar el cierre de la variable de matriz:

uniqueArray = myArray.filter(function(item, pos, self) {
    return self.indexOf(item) == pos;
})

Aunque conciso, este algoritmo no es especialmente eficiente para grandes conjuntos (cuadrática tiempo).

Tablas de hash para el rescate

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

Así es como se hace usualmente. La idea es colocar cada elemento en una tabla hash y, a continuación, comprobar su presencia al instante. Esto nos da el tiempo lineal, pero tiene al menos dos inconvenientes:

  • desde hash de las claves sólo puede ser cadenas en Javascript, este código no distingue a los números y "numéricos en cadenas de caracteres". Es decir, uniq([1,"1"]) devuelve [1]
  • por la misma razón, todos los objetos se considerará igual a: uniq([{foo:1},{foo:2}]) devuelve [{foo:1}].

Dicho esto, si las matrices contienen sólo las primitivas y no se preocupan por tipos (por ejemplo, siempre los números), esta solución es la óptima.

Lo mejor de dos mundos

Una solución universal que combina ambos enfoques: utiliza el hash de las búsquedas de primitivas y lineal de búsqueda de objetos.

function uniq(a) {
    var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

    return a.filter(function(item) {
        var type = typeof item;
        if(type in prims)
            return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
        else
            return objs.indexOf(item) >= 0 ? false : objs.push(item);
    });
}

sort | uniq

Otra opción es ordenar el array en primer lugar, y, a continuación, retire cada elemento igual a la anterior:

function uniq(a) {
    return a.sort().filter(function(item, pos) {
        return !pos || item != a[pos - 1];
    })
}

De nuevo, esto no funciona con objetos (porque todos los objetos son iguales para sort). Además, este método de forma silenciosa de los cambios de la matriz original como un efecto secundario - no es bueno!

Única por...

A veces se desea uniquify una lista basada en algunos criterios que no sólo la igualdad, por ejemplo, para filtrar los objetos de los que son distintos, pero comparten ciertas propiedades. Esto se puede hacer con elegancia por el paso de una devolución de llamada, generalmente se llama una "clave". key() se aplica a cada elemento, y de los elementos de la igualdad de las "claves" son eliminados. Desde key que se espera para volver a una primitiva, la tabla hash funcionará bien aquí:

function uniqBy(a, key) {
    var seen = {};
    return a.filter(function(item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    })
}

Especialmente útil key() es JSON.stringify que ayuda a filtrar los objetos con la misma estructura:

a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]

388voto

Roman Bataev Puntos 2806

Rápido y sucio utilizando jQuery:

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
    if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});

289voto

Christian Landgren Puntos 1127

Se cansó de ver a todos los malos ejemplos con lazos para la o jQuery. JavaScript tiene las herramientas perfectas para esto hoy en día: ordenar, mapa y reducir.

Uniq reducir manteniendo el orden existente

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

var uniq = names.reduce(function(a,b){
    if (a.indexOf(b) < 0 ) a.push(b);
    return a;
  },[]);

console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);

Uniq más rápido con clasificación

Hay maneras probablemente más rápidos pero es bastante decente.

var uniq = names.slice() // slice makes copy of array before sorting it
  .sort(function(a,b){
    return a - b;
  })
  .reduce(function(a,b){
    if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
    return a;
  },[]); // this empty array becomes the starting value for a

// one liner
return names.slice().sort(function(a,b){return a - b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);

81voto

Darthfett Puntos 1645

Siempre puedes probar a ponerlo en un objeto y luego recorrer sus claves:

a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
b = {};
for (var i = 0; i < a.length; i++) {
    b[a[i]] = a[i];
}
c = [];
for (var key in b) {
    c.push(key);
}
//c:
//["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]

69voto

Brandon Boone Puntos 8372

Uso Underscore.js

Es una biblioteca con una variedad de funciones para la manipulación de matrices.

Esa es la corbata para ir junto con jQuery tux, y Backbone.js del tirantes.

_.uniq

_.uniq(array, [isSorted], [iterator]) Alias: único
Produce un duplicado de la versión libre de la matriz, usando === a la del objeto de la prueba la igualdad. Si usted sabe de antemano que el array está ordenado, pasando verdadero para isSorted se ejecutará mucho más rápido algoritmo. Si quieres calcular únicos elementos en función de una transformación, pasar un iterador función.

Ejemplo

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

alert(_.uniq(names, false));

Nota: Lo-Dash (un carácter de subrayado competidor) también ofrece una comparables .uniq aplicación.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X