Tengo una serie de números que necesito para asegurarme de que sean únicos. Encontré el fragmento de código a continuación en Internet y funciona muy bien hasta que la matriz tiene un cero. Encontré este otro script aquí en Stack Overflow que se ve casi exactamente igual, pero no falla.
Entonces, en aras de ayudarme a aprender, ¿alguien puede ayudarme a determinar dónde va mal el script prototipo?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Más respuestas de preguntas duplicadas:
Pregunta similar:
javascript
arrays
unique
Mottie
fuente
fuente
o
=object
,a
=array
,i
=index
ye
= umm, algo: PRespuestas:
Con JavaScript 1.6 / ECMAScript 5 puede usar el
filter
método nativo de una matriz de la siguiente manera para obtener una matriz con valores únicos:El método nativo
filter
recorrerá la matriz y dejará solo aquellas entradas que pasen la función de devolución de llamada dadaonlyUnique
.onlyUnique
comprueba, si el valor dado es el primero que ocurre. De lo contrario, debe ser un duplicado y no se copiará.Esta solución funciona sin ninguna biblioteca adicional como jQuery o prototype.js.
Funciona también para matrices con tipos de valores mixtos.
Para los navegadores antiguos (<ie9), que no admiten los métodos nativos
filter
yindexOf
puede encontrar soluciones alternativas en la documentación de MDN para filter e indexOf .Si desea mantener la última aparición de un valor, simplemente reemplace
indexOf
porlastIndexOf
.Con ES6 se podría acortar a esto:
Gracias a Camilo Martin por la pista en el comentario.
ES6 tiene un objeto nativo
Set
para almacenar valores únicos. Para obtener una matriz con valores únicos, ahora puede hacer esto:El constructor de
Set
toma un objeto iterable, como Array, y el operador de propagación...
transforma el conjunto nuevamente en un Array. Gracias a Lukas Liese por la pista en el comentario.fuente
['a', 1, 'a', 2, '1']
, obtendrías['a', 1, 2]
. Pero esto no es lo que esperaba. Por cierto, mucho más lento es muy relativo..filter((v,i,a)=>a.indexOf(v)==i)
(notación de flecha gruesa).let unique_values = [...new Set(random_array)];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Respuesta actualizada para ES6 / ES2015 : Usando el Set , la solución de línea única es:
Que vuelve
Como le_m sugirió, esto también se puede acortar usando el operador de propagación , como
fuente
Array.from(new Set([[1,2],[1,2],[1,2,3]]))
myArray.filter((v, i, a) => a.indexOf(v) === i);
?Set
y agrega objetos en lugar de valores primitivos, contendrá referencias únicas a los objetos. Así, el conjuntos
enlet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
volverá esto:Set { { Foo: 'Bar' }, { Foo: 'Bar' } }
que es unaSet
con referencias a objetos únicos a objetos que contienen los mismos valores. Si escribelet o = {Foo:"Bar"};
y luego crea un conjunto con dos referencias como esta:let s2 = new Set([o,o]);
entonces s2 seráSet { { Foo: 'Bar' } }
new Set
el trofeoMe doy cuenta de que esta pregunta ya tiene más de 30 respuestas. Pero primero leí todas las respuestas existentes e hice mi propia investigación.
Dividí todas las respuestas a 4 posibles soluciones:
[...new Set( [1, 1, 2] )];
{ }
para evitar duplicados[ ]
filter + indexOf
Aquí hay ejemplos de códigos encontrados en las respuestas:
Use la nueva función ES6:
[...new Set( [1, 1, 2] )];
Usar objeto
{ }
para evitar duplicadosUsar matriz auxiliar
[ ]
Utilizar
filter + indexOf
Y me preguntaba cuál es más rápido. Hice una muestra de Google Sheet para probar funciones. Nota: ECMA 6 no está disponible en Hojas de cálculo de Google, por lo que no puedo probarlo.
Aquí está el resultado de las pruebas:
Esperaba ver que el código que usa el objeto
{ }
ganará porque usa hash. Así que me alegro de que las pruebas mostraron los mejores resultados para este algoritmo en Chrome e IE. Gracias a @rab por el código .fuente
También puedes usar underscore.js .
que devolverá:
fuente
array = [...new Set(array)]
One Liner, JavaScript puro
Con sintaxis ES6
list = list.filter((x, i, a) => a.indexOf(x) == i)
Con sintaxis ES5
Compatibilidad del navegador : IE9 +
fuente
Desde entonces he encontrado un buen método que usa jQuery
Nota: Este código fue retirado del puesto de perforación de pato de Paul Irish - Me olvidé de dar crédito: P
fuente
La solución más corta con ES6:
[...new Set( [1, 1, 2] )];
O si desea modificar el prototipo de matriz (como en la pregunta original):
Por el momento, EcmaScript 6 solo se implementa parcialmente en los navegadores modernos (agosto de 2015), pero Babel se ha vuelto muy popular por trasladar ES6 (e incluso ES7) a ES5. ¡De esa manera puedes escribir el código ES6 hoy!
Si se pregunta qué
...
significa, se llama operador de propagación . Desde MDN : «El operador de propagación permite que una expresión se expanda en lugares donde se esperan múltiples argumentos (para llamadas a funciones) o múltiples elementos (para literales de matriz)». Debido a que un conjunto es iterable (y solo puede tener valores únicos), el operador de expansión expandirá el conjunto para llenar la matriz.Recursos para aprender ES6:
fuente
a = [...Set(a)]
pero, de todos modos, esto es solo Firefox, por ahora.require ( "core-js/fn/array/from" );
[...Set(['a', 1, 'a', 2, '1'])]
lanzará un TypeError, por lo que es prudente retener elnew
:[...new Set(['a', 1, 'a', 2, '1'])]
La solución más simple:
O:
fuente
La forma más simple y rápida (en Chrome) de hacer esto:
Simplemente revisa todos los elementos de la matriz, comprueba si ese elemento ya está en la lista y, si no lo está, pasa a la matriz que se devuelve.
Según jsPerf, esta función es la más rápida de las que pude encontrar en cualquier lugar ; no obstante, siéntase libre de agregar la suya.
La versión no prototipo:
Clasificación
Cuando también se necesita ordenar la matriz, lo siguiente es lo más rápido:
o no prototipo:
Esto también es más rápido que el método anterior en la mayoría de los navegadores que no son de Chrome.
fuente
unique
función tiene complejidad O (n ^ 2) mientras que el quegetUnique
está en es O (n). El primero puede ser más rápido en conjuntos de datos pequeños, pero ¿cómo puede discutir con las matemáticas :) Puede asegurarse de que el último sea más rápido si lo ejecuta en una matriz de, por ejemplo, 1e5 elementos únicosRENDIMIENTO SOLO! este código es probablemente 10 veces más rápido que todos los códigos aquí * funciona en todos los navegadores y también tiene el menor impacto en la memoria ... y más
si no necesita reutilizar la matriz anterior; por cierto, haga las otras operaciones necesarias antes de convertirla en única aquí, probablemente sea la forma más rápida de hacerlo, también muy breve.
entonces puedes probar esto
Se me ocurrió esta función leyendo este artículo ...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
No me gusta el bucle for. tiene muchos parámetros. Me gusta el bucle while. while es el bucle más rápido en todos los navegadores, excepto el que a todos nos gusta tanto ... Chrome.
de todos modos, escribí la primera función que usa while. Y sí, es un poco más rápido que la función encontrada en el artículo. pero no lo suficiente.
unique2()
El siguiente paso es usar js modernos.
Object.keys
Reemplacé el otro bucle for con Object.keys de js1.7 ... un poco más rápido y más corto (en Chrome 2x más rápido);). ¡No es suficiente!.unique3()
.En este punto estaba pensando en lo que realmente necesito en MI función única. No necesito la matriz anterior, quiero una función rápida. así que usé 2 while loops + splice.
unique4()
Inútil decir que estaba impresionado.
cromo: las 150,000 operaciones habituales por segundo aumentaron a 1,800,000 operaciones por segundo.
es decir: 80,000 op / s vs 3,500,000 op / s
ios: 18,000 op / s vs 170,000 op / s
safari: 80,000 op / s vs 6,000,000 op / s
Prueba http://jsperf.com/wgu o mejor usa console.time ... microtime ... lo que sea
unique5()
es solo para mostrarle lo que sucede si desea mantener la matriz anterior.No lo uses
Array.prototype
si no sabes lo que estás haciendo. Acabo de hacer un montón de copia y pasado. ÚseloObject.defineProperty(Array.prototype,...,writable:false,enumerable:false})
si desea crear un prototipo nativo. Ejemplo: https://stackoverflow.com/a/20463021/2450730Demo http://jsfiddle.net/46S7g/
NOTA: su matriz anterior se destruye / se vuelve única después de esta operación.
si no puede leer el código anterior, pregunte, lea un libro de JavaScript o aquí hay algunas explicaciones sobre el código más corto. https://stackoverflow.com/a/21353032/2450730
algunos están usando
indexOf
... no ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhpara matrices vacías
fuente
Muchas de las respuestas aquí pueden no ser útiles para principiantes. Si la eliminación de la duplicación de una matriz es difícil, ¿sabrán realmente sobre la cadena de prototipos, o incluso sobre jQuery?
En los navegadores modernos, una solución limpia y simple es almacenar datos en un Conjunto , que está diseñado para ser una lista de valores únicos.
Esto
Array.from
es útil para convertir el conjunto de nuevo a una matriz para que tenga fácil acceso a todos los métodos (características) increíbles que tienen las matrices. También hay otras formas de hacer lo mismo. Pero es posible que no necesiteArray.from
nada, ya que los Sets tienen muchas características útiles como forEach .Si necesita admitir Internet Explorer anterior y, por lo tanto, no puede usar Set, una técnica simple es copiar los elementos en una nueva matriz y verificar de antemano si ya están en la nueva matriz.
Para que esto sea reutilizable al instante, vamos a ponerlo en una función.
Entonces, para deshacernos de los duplicados, ahora haríamos esto.
La
deduplicate(cars)
parte se convierte en lo que llamamos resultado cuando se completa la función.Simplemente pásele el nombre de cualquier matriz que desee.
fuente
fuente
push
el elemento en la matriz en lugar de usarconcat
? Intenté usar push y falló. Estoy buscando una explicación.[0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
NaN
amigablePodemos hacer esto usando conjuntos ES6:
// La salida será
fuente
Este prototipo
getUnique
no es totalmente correcto, porque si tengo una matriz como:["1",1,2,3,4,1,"foo"]
volverá["1","2","3","4"]
y"1"
es una cadena y1
es un número entero; ellos son diferentes.Aquí hay una solución correcta:
utilizando:
Lo anterior producirá
["1",2,3,4,1,"foo"]
.fuente
$foo = 'bar'
es la forma PHP de declarar variables. Funcionará en JavaScript, pero creará un global implícito, y generalmente no debería hacerse.$foo
es la forma de declarar variables en JavaScript mientras que en realidad lovar foo
es.Sin extender Array.prototype (se dice que es una mala práctica) o usar jquery / subrayado, puede simplemente
filter
la matriz.Al mantener la última ocurrencia:
o primera aparición:
Bueno, es solo JavaScript ECMAScript 5+, lo que significa solo IE9 +, pero es bueno para un desarrollo en HTML / JS nativo (aplicación de la Tienda Windows, Firefox OS, Sencha, Phonegap, Titanium, ...).
fuente
filter
. En la página MDN tienen una implementación para Internet Explorer, quiero decir, navegadores más antiguos. Además: JS 1.6 se refiere solo al motor js de Firefox, pero lo correcto es decir que es ECMAScript 5.magia
O (n) rendimiento ; asumimos que su matriz está en
a
yt={}
. Explicación aquí (+ Jeppe impr.)Mostrar fragmento de código
fuente
in
operador fuera de la otra construcción que no sea elfor
bucle: P) - Gracias - Lo aprecio y le daré +2 a sus otras buenas respuestas .t
que se mantiene viva después del filtrado ... ??fuente
Si está utilizando Prototype framework, no es necesario hacer bucles 'for', puede usar http://www.prototypejs.org/api/array/uniq de esta manera:
Lo que producirá una matriz duplicada sin duplicados. Encontré su pregunta buscando un método para contar distintos registros de matriz, así que después
solía
y ahí estaba mi resultado simple. PD Lo siento si me equivoqué algo
editar: si desea escapar de registros indefinidos, puede agregar
antes, así:
fuente
Ahora, usando conjuntos, puede eliminar duplicados y convertirlos nuevamente a la matriz.
Otra solución es usar ordenar y filtrar
fuente
Eso es porque
0
es un valor falso en JavaScript.this[i]
será falso si el valor de la matriz es 0 o cualquier otro valor falso.fuente
fuente
o
lugar de solo a1
, aunque la comparación de igualdad seguiría siendo secuencial (aunque, de todas las posibles igualdades de Javascript, no parece demasiado irrazonable).Tuve un problema ligeramente diferente en el que necesitaba eliminar objetos con propiedades de identificación duplicadas de una matriz. Esto funcionó.
fuente
La respuesta más simple es:
fuente
No estoy seguro de por qué Gabriel Silveira escribió la función de esa manera, pero una forma más simple que funciona para mí igual de bien y sin la minificación es:
o en CoffeeScript:
fuente
Si está de acuerdo con las dependencias adicionales, o si ya tiene una de las bibliotecas en su base de código, puede eliminar duplicados de una matriz en su lugar utilizando LoDash (o subrayado).
Uso
Si aún no lo tiene en su base de código, instálelo usando npm:
Luego úsalo de la siguiente manera:
Fuera:
fuente
Esto ha sido respondido mucho, pero no atendió mi necesidad particular.
Muchas respuestas son así:
Pero esto no funciona para matrices de objetos complejos.
Digamos que tenemos una matriz como esta:
Si queremos los objetos con nombres únicos, deberíamos usar en
array.prototype.findIndex
lugar dearray.prototype.indexOf
:fuente
De Shamasis Bhattacharya el blog 's (complejidad O (2n)):
Del blog de Paul Irish : mejora en JQuery
.unique()
:fuente
Encontrar valores únicos de matriz en un método simple
fuente
Parece que hemos perdido la respuesta de Rafael , que se mantuvo como la respuesta aceptada durante algunos años. Esta fue (al menos en 2017) la solución de mejor rendimiento si no tiene una matriz de tipo mixto :
Si hacer un arreglo de tipo mixto, puede serializar la tecla de almohadilla:
fuente
Para solucionar el problema al revés, puede ser útil no tener duplicados mientras carga su matriz, de la forma en que lo haría el objeto Set , pero aún no está disponible en todos los navegadores. Ahorra memoria y es más eficiente si necesita ver su contenido muchas veces.
Muestra:
Te dio
set = [1,3,4,2]
fuente