valores repetidos query objetos eliminar elementos contar buscar array javascript arrays duplicates unique

javascript - repetidos - Eliminar valores duplicados de la matriz JS



query array javascript (30)

Esta pregunta ya tiene una respuesta aquí:

Tengo una matriz de JavaScript muy simple que puede o no contener duplicados.

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

Necesito eliminar los duplicados y colocar los valores únicos en una nueva matriz.

Podría señalar todos los códigos que he probado, pero creo que es inútil porque no funcionan. Acepto las soluciones jQuery también.

Pregunta similar:


usar Array.filter() como este

var actualArr = [''Apple'', ''Apple'', ''Banana'', ''Mango'', ''Strawberry'', ''Banana'']; console.log(''Actual Array: '' + actualArr); var filteredArr = actualArr.filter(function(item, index) { if (actualArr.indexOf(item) == index) return item; }); console.log(''Filtered Array: '' + filteredArr);

Esto se puede hacer más corto en ES6 para

actualArr.filter((item,index,self) => self.indexOf(item)==index);

Here está una buena explicación de Array.filter()


Manera "inteligente" pero ingenua.

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

Básicamente, iteramos sobre la matriz y, para cada elemento, verificamos si la primera posición de este elemento en la matriz es igual a la posición actual. Obviamente, estas dos posiciones son diferentes para elementos duplicados.

Usando el tercer parámetro ("esta matriz") de la devolución de llamada del filtro, podemos evitar el cierre de la variable de la matriz:

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

Aunque conciso, este algoritmo no es particularmente eficiente para arreglos grandes (tiempo cuadrático).

Hashtables al rescate.

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

Así es como se hace normalmente. La idea es colocar cada elemento en una tabla hash y luego verificar su presencia al instante. Esto nos da un tiempo lineal, pero tiene al menos dos inconvenientes:

  • Dado que las claves hash solo pueden ser cadenas en Javascript, este código no distingue números y "cadenas numéricas". Es decir, uniq([1,"1"]) devolverá solo [1]
  • por la misma razón, todos los objetos se considerarán iguales: uniq([{foo:1},{foo:2}]) devolverá solo [{foo:1}] .

Dicho esto, si sus arreglos contienen solo primitivos y no le importan los tipos (por ejemplo, siempre son números), esta solución es óptima.

Lo mejor de dos mundos.

Una solución universal combina ambos enfoques: utiliza búsquedas de hash para primitivos y búsqueda lineal 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); }); }

ordenar uniq

Otra opción es ordenar la matriz primero y luego eliminar cada elemento igual al anterior:

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

Nuevamente, esto no funciona con objetos (porque todos los objetos son iguales para sort ). Además, cambiamos silenciosamente la matriz original como efecto secundario, ¡no es bueno! Sin embargo, si su entrada ya está ordenada, esta es la forma de hacerlo (solo elimine la sort de la anterior).

Único por ...

A veces, se desea unificar una lista en función de algunos criterios distintos de la igualdad, por ejemplo, para filtrar objetos que son diferentes, pero compartir alguna propiedad. Esto se puede hacer elegantemente pasando una devolución de llamada. Esta devolución de llamada "clave" se aplica a cada elemento y se eliminan los elementos con "claves" iguales. Como se espera que la key devuelva 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); }) }

Una key() particularmente útil key() es JSON.stringify que eliminará los objetos que son físicamente diferentes, pero que "lucen" iguales:

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

Si la key no es primitiva, debe recurrir a la búsqueda lineal:

function uniqBy(a, key) { var index = []; return a.filter(function (item) { var k = key(item); return index.indexOf(k) >= 0 ? false : index.push(k); }); }

o use el objeto Set en ES6:

function uniqBy(a, key) { var seen = new Set(); return a.filter(item => { var k = key(item); return seen.has(k) ? false : seen.add(k); }); }

(Algunas personas prefieren !seen.has(k) && seen.add(k) lugar de seen.has(k) ? false : seen.add(k) ).

Bibliotecas

Tanto el underscore como Lo-Dash proporcionan métodos uniq . Sus algoritmos son básicamente similares al primer fragmento de código anterior y se reducen a esto:

var result = []; a.forEach(function(item) { if(result.indexOf(item) < 0) { result.push(item); } });

Esto es cuadrático, pero hay buenos indexOf adicionales, como envolver indexOf nativo, la capacidad de unificar mediante una clave ( iteratee en su lenguaje) y las optimizaciones para arreglos ya ordenados.

Si estás usando jQuery y no puedes soportar nada sin un dólar antes, es así:

$.uniqArray = function(a) { return $.grep(a, function(item, pos) { return $.inArray(item, a) === pos; }); }

que es, una vez más, una variación del primer fragmento.

Actuación

Las llamadas a funciones son costosas en Javascript, por lo tanto, las soluciones anteriores, por concisas que sean, no son particularmente eficientes. Para obtener el máximo rendimiento, reemplace el filter con un bucle y deshágase de otras llamadas a funciones:

function uniq_fast(a) { var seen = {}; var out = []; var len = a.length; var j = 0; for(var i = 0; i < len; i++) { var item = a[i]; if(seen[item] !== 1) { seen[item] = 1; out[j++] = item; } } return out; }

Este fragmento de código feo hace lo mismo que el fragmento de código # 3 anterior, pero un orden de magnitud más rápido (a partir de 2017 es solo el doble de rápido: ¡la gente de JS está haciendo un gran trabajo!)

function uniq(a) { var seen = {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seen[item] = true); }); } function uniq_fast(a) { var seen = {}; var out = []; var len = a.length; var j = 0; for(var i = 0; i < len; i++) { var item = a[i]; if(seen[item] !== 1) { seen[item] = 1; out[j++] = item; } } return out; } ///// var r = [0,1,2,3,4,5,6,7,8,9], a = [], LEN = 1000, LOOPS = 1000; while(LEN--) a = a.concat(r); var d = new Date(); for(var i = 0; i < LOOPS; i++) uniq(a); document.write(''<br>uniq, ms/loop: '' + (new Date() - d)/LOOPS) var d = new Date(); for(var i = 0; i < LOOPS; i++) uniq_fast(a); document.write(''<br>uniq_fast, ms/loop: '' + (new Date() - d)/LOOPS)

ES6

ES6 proporciona el objeto Set , que hace las cosas mucho más fáciles:

function uniq(a) { return Array.from(new Set(a)); }

o

let uniq = a => [...new Set(a)];

Tenga en cuenta que, a diferencia de python, los conjuntos de ES6 se iteran en el orden de inserción, por lo que este código conserva el orden de la matriz original.

Sin embargo, si necesita una matriz con elementos únicos, ¿por qué no usar conjuntos desde el principio?

Generadores

Una versión "perezosa" basada en el generador de uniq se puede construir sobre la misma base:

  • toma el siguiente valor del argumento
  • Si ya se ha visto, sáltate.
  • De lo contrario, cámbielo y agréguelo al conjunto de valores ya vistos.

function* uniqIter(a) { let seen = new Set(); for (let x of a) { if (!seen.has(x)) { seen.add(x); yield x; } } } // example: function* randomsBelow(limit) { while (1) yield Math.floor(Math.random() * limit); } // note that randomsBelow is endless count = 20; limit = 30; for (let r of uniqIter(randomsBelow(limit))) { console.log(r); if (--count === 0) break } // exercise for the reader: what happens if we set `limit` less than `count` and why


Utilice Underscore.js

Es una biblioteca con una gran cantidad de funciones para manipular matrices.

Es el empate para ir junto con el esmoquin de jQuery y los tirantes de Backbone.js.

underscore

_.uniq(array, [isSorted], [iterator]) Alias: único
Produce una versión libre de duplicados de la matriz , utilizando === para probar la igualdad de objetos. Si sabe de antemano que la matriz está ordenada, el paso verdadero para isSorted ejecutará un algoritmo mucho más rápido. Si desea calcular elementos únicos basados ​​en una transformación, pase una función de iterador .

Example

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; alert(_.uniq(names, false));

Nota: Lo-Dash (un competidor de Underscore.js ) también ofrece una implementación de lodash.com/docs#uniq comparable.


Enfoque funcional genérico

Aquí hay un enfoque genérico y estrictamente funcional con ES2015:

// small, reusable auxiliary functions const apply = f => a => f(a); const flip = f => b => a => f(a) (b); const uncurry = f => (a, b) => f(a) (b); const push = x => xs => (xs.push(x), xs); const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); const some = f => xs => xs.some(apply(f)); // the actual de-duplicate function const uniqueBy = f => foldl( acc => x => some(f(x)) (acc) ? acc : push(x) (acc) ) ([]); // comparators const eq = y => x => x === y; // string equality case insensitive :D const seqCI = y => x => x.toLowerCase() === y.toLowerCase(); // mock data const xs = [1,2,3,1,2,3,4]; const ys = ["a", "b", "c", "A", "B", "C", "D"]; console.log( uniqueBy(eq) (xs) ); console.log( uniqueBy(seqCI) (ys) );

Podemos deducir fácilmente uniquea partir de unqiueByo utilizar la aplicación más rápida que utiliza Sets:

const unqiue = uniqueBy(eq); // const unique = xs => Array.from(new Set(xs));

Beneficios de este enfoque:

  • Solución genérica mediante el uso de una función de comparación separada
  • Implementación declarativa y sucinta.
  • Reutilización de otras funciones pequeñas, genéricas.

Consideraciones de rendimiento

uniqueBy no es tan rápida como una implementación imperativa con bucles, pero es mucho más expresiva debido a su genérico.

Si se identifica uniqueBycomo la causa de una penalización de rendimiento concreta en su aplicación, sustitúyala por un código optimizado. Es decir, escriba su código primero de manera funcional y declarativa. Luego, siempre que encuentre problemas de rendimiento, intente optimizar el código en las ubicaciones, que son la causa del problema.

Consumo de memoria y recolección de basura

uniqueByUtiliza mutaciones ( push(x) (acc)) ocultas dentro de su cuerpo. Reutiliza el acumulador en lugar de tirarlo después de cada iteración. Esto reduce el consumo de memoria y la presión GC. Dado que este efecto secundario está envuelto dentro de la función, todo lo que permanece afuera permanece puro.


Aquí hay una respuesta simple a la pregunta.

var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"]; var uniqueNames = []; for(var i in names){ if(uniqueNames.indexOf(names[i]) === -1){ uniqueNames.push(names[i]); } }


El más simple que he encontrado hasta ahora. En es6.

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"] var noDupe = Array.from(new Set(names))

Set


En ECMAScript 6 (también conocido como ECMAScript 2015), Set se puede usar para filtrar duplicados. Luego se puede convertir de nuevo a una matriz utilizando el operador de propagación .

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"], unique = [...new Set(names)];


Había hecho una comparación detallada de la eliminación de duplicados en otra pregunta, pero habiendo notado que este es el lugar real, solo quería compartirlo aquí también.

Creo que esta es la mejor manera de hacer esto.

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200], reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{})); console.log(reduced);

OK ... aunque este es O (n) y los otros O (n ^ 2) tenía curiosidad por ver una comparación de referencia entre esta tabla de reducción / consulta y el combo filter / indexOf (elijo Jeetendras muy buena implementación https://.com/a/37441144/4543207 ). Preparo una matriz de elementos de 100K rellenada con enteros positivos aleatorios en el rango 0-9999 y elimina los duplicados. Repito la prueba 10 veces y el promedio de los resultados muestra que no hay coincidencia en el rendimiento.

  • En Firefox v47 reduce & lut: 14.85ms vs filter & indexOf: 2836ms
  • En Chrome v51 reduce & lut: 23.90ms vs filter & indexOf: 1066ms

Bien, bien, hasta ahora, bien. Pero hagámoslo correctamente esta vez en el estilo ES6. ¡Se ve tan genial ..! Pero a partir de ahora, cómo se desempeñará contra la poderosa solución de lut es un misterio para mí. Veamos primero el código y luego lo comparamos.

var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200], reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()]; console.log(reduced);

Wow eso fue corto ..! Pero ¿qué hay del rendimiento ...? Es hermoso ... Debido a que el peso pesado del filtro / índice sobre nuestros hombros ahora puedo probar una matriz de 1M de elementos enteros positivos en el rango de 0..99999 para obtener un promedio de 10 pruebas consecutivas. Puedo decir que esta vez es un partido real. Mira el resultado por ti mismo :)

var ranar = [], red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})), red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 10; for (var i = 0; i<count; i++){ ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("reduce & lut took: " + avg1 + "msec"); console.log("map & spread took: " + avg2 + "msec");

¿Cuál usarías ...? Bueno, no tan rápido ...! No te dejes engañar. El mapa está en desplazamiento. Ahora mire ... en todos los casos anteriores llenamos una matriz de tamaño n con números de rango <n. Quiero decir que tenemos una matriz de tamaño 100 y rellenamos con números aleatorios 0..9 por lo que hay duplicados definidos y "casi" definitivamente cada número tiene un duplicado. ¿Qué tal si llenamos la matriz en tamaño 100 con números aleatorios 0..9999? Veamos ahora el mapa jugando en casa. Esta vez, una matriz de 100K elementos pero el rango de números aleatorios es 0..100M. Haremos 100 pruebas consecutivas para promediar los resultados. OK vamos a ver las apuestas ..! <- sin error tipográfico

var ranar = [], red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})), red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 100; for (var i = 0; i<count; i++){ ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("reduce & lut took: " + avg1 + "msec"); console.log("map & spread took: " + avg2 + "msec");

Ahora este es el espectacular regreso de Map () ..! Puede ser que ahora puedas tomar una mejor decisión cuando quieras eliminar a los duplicados.

Bien, bien, todos estamos felices ahora. Pero el papel principal siempre llega en último lugar con algunos aplausos. Estoy seguro de que algunos de ustedes se preguntan qué haría Set object. Ahora que estamos abiertos a ES6 y sabemos que Map es el ganador de los juegos anteriores, comparemos Map with Set como final. Un juego típico del Real Madrid vs Barcelona esta vez ... ¿o no? A ver quién ganará el classico :)

var ranar = [], red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()], red2 = a => Array.from(new Set(a)), avg1 = [], avg2 = [], ts = 0, te = 0, res1 = [], res2 = [], count= 100; for (var i = 0; i<count; i++){ ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000)); ts = performance.now(); res1 = red1(ranar); te = performance.now(); avg1.push(te-ts); ts = performance.now(); res2 = red2(ranar); te = performance.now(); avg2.push(te-ts); } avg1 = avg1.reduce((p,c) => p+c)/count; avg2 = avg2.reduce((p,c) => p+c)/count; console.log("map & spread took: " + avg1 + "msec"); console.log("set & A.from took: " + avg2 + "msec");

Wow hombre..! Bueno, inesperadamente, no resultó ser un clásico en absoluto. Más como el Barcelona FC contra el CA Osasuna :))


La forma más concisa de eliminar duplicados de una matriz utilizando funciones de JavaScript nativas es usar una secuencia como la siguiente:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])

no hay necesidad de slice ni indexOf dentro de la función de reducción, ¡como he visto en otros ejemplos! Sin embargo, tiene sentido utilizarlo junto con una función de filtro:

vals.filter(function(v, i, a){ return i == a.indexOf(v) })

Otra forma de hacer esto de ES6 (2015) que ya funciona en algunos navegadores es:

Array.from(new Set(vals))

o incluso utilizando el operador de propagación :

[...new Set(vals)]

¡aclamaciones!


Lo siguiente es más del 80% más rápido que el método de jQuery listado (vea las pruebas a continuación). Es una respuesta de una pregunta similar hace unos años. Si me encuentro con la persona que lo propuso originalmente, publicaré el crédito. Puro JS.

var temp = {}; for (var i = 0; i < array.length; i++) temp[array[i]] = true; var r = []; for (var k in temp) r.push(k); return r;

Mi comparación de caso de prueba: http://jsperf.com/remove-duplicate-array-tests


Me cansé de ver todos los malos ejemplos con for-loops o jQuery. Javascript tiene las herramientas perfectas para esto hoy en día: ordenar, mapear y reducir.

Uniq reduce manteniendo 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 la clasificación

Probablemente hay maneras más rápidas, pero esta 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;},[]);

Actualización 2015: versión ES6:

En ES6 tienes Sets and Spread, lo que hace que sea muy fácil y eficaz eliminar todos los duplicados:

var uniq = [ ...new Set(names) ]; // [ ''Mike'', ''Matt'', ''Nancy'', ''Adam'', ''Jenny'', ''Carl'' ]

Clasificación basada en la ocurrencia:

Alguien preguntó acerca de cómo ordenar los resultados según la cantidad de nombres únicos que existen:

var names = [''Mike'', ''Matt'', ''Nancy'', ''Adam'', ''Jenny'', ''Nancy'', ''Carl''] var uniq = names .map((name) => { return {count: 1, name: name} }) .reduce((a, b) => { a[b.name] = (a[b.name] || 0) + b.count return a }, {}) var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b]) console.log(sorted)


Rápido y sucio usando 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); });


Simplemente puede hacerlo en JavaScript, con la ayuda del segundo parámetro de índice del método de filter :

var a = [2,3,4,5,5,4]; a.filter(function(value, index){ return a.indexOf(value) == index });

o en mano corta

a.filter((v,i) => a.indexOf(v) == i)


Una línea:

let names = [''Mike'',''Matt'',''Nancy'',''Adam'',''Jenny'',''Nancy'',''Carl'', ''Nancy'']; let dup = [...new Set(names)]; console.log(dup);


Una técnica simple pero efectiva es usar el método de filter en combinación con la function(value, index){ return this.indexOf(value) == index } filtro function(value, index){ return this.indexOf(value) == index } .

Ejemplo de código:

var data = [2,3,4,5,5,4]; var filter = function(value, index){ return this.indexOf(value) == index }; var filteredData = data.filter(filter, data ); document.body.innerHTML = ''<pre>'' + JSON.stringify(filteredData, null, ''/t'') + ''</pre>'';

Véase también este violín .


Una versión de línea única que usa el filtro de matriz y las funciones indexOf:

arr = arr.filter (function (value, index, array) { return array.indexOf (value) == index; });


Ve por este

var uniqueArray = duplicateArray.filter(function(elem, pos) { return duplicateArray.indexOf(elem) == pos; });

Ahora uniqueArray no contiene duplicados.


https://jsfiddle.net/2w0k5tz8/

function remove_duplicates(array_){ var ret_array = new Array(); for (var a = array_.length - 1; a >= 0; a--) { for (var b = array_.length - 1; b >= 0; b--) { if(array_[a] == array_[b] && a != b){ delete array_[b]; } }; if(array_[a] != undefined) ret_array.push(array_[a]); }; return ret_array; } console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));

Recorra, elimine duplicados y cree un marcador de lugar de matriz clonada porque el índice de matriz no se actualizará.

Bucle hacia atrás para un mejor rendimiento (su bucle no tendrá que seguir controlando la longitud de su matriz)


Aquí está el método simple, sin bibliotecas especiales son funciones especiales,

name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; }) console.log("Original name list:"+name_list.length, name_list) console.log("/n Unique name list:"+get_uniq.length, get_uniq)


Esta es probablemente una de las maneras más rápidas de eliminar de forma permanente los duplicados de una matriz 10 veces más rápido que la mayoría de las funciones aquí.

function toUnique(a,b,c){ //array,placeholder,placeholder b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1) }

  1. Prueba: http://jsperf.com/wgu
  2. Demostración: http://jsfiddle.net/46S7g/
  3. Más: https://.com/a/25082874/2450730

Si no puedes leer el código anterior, pregunta, lee un libro de JavaScript o aquí hay algunas explicaciones sobre el código más corto. https://.com/a/21353032/2450730


Solución 1

Array.prototype.unique = function() { var a = []; for (i = 0; i < this.length; i++) { var current = this[i]; if (a.indexOf(current) < 0) a.push(current); } return a; }

Solución 2 (usando Set)

Array.prototype.unique = function() { return Array.from(new Set(this)); }

Prueba

var x=[1,2,3,3,2,1]; x.unique() //[1,2,3]

Actuación

Cuando probé el rendimiento en Chrome en ambas implementaciones (con y sin Set), ¡encontré que la de Set es mucho más rápida!

Array.prototype.unique1 = function() { var a = []; for (i = 0; i < this.length; i++) { var current = this[i]; if (a.indexOf(current) < 0) a.push(current); } return a; } Array.prototype.unique2 = function() { return Array.from(new Set(this)); } var x=[]; for(var i=0;i<10000;i++){ x.push("x"+i);x.push("x"+(i+1)); } console.time("unique1"); console.log(x.unique1()); console.timeEnd("unique1"); console.time("unique2"); console.log(x.unique2()); console.timeEnd("unique2");


Vanilla JS: elimine los duplicados usando un objeto como un conjunto

Siempre puedes intentar colocarlo en un objeto y luego iterarlo a través de sus teclas:

function remove_duplicates(arr) { var obj = {}; var ret_arr = []; for (var i = 0; i < arr.length; i++) { obj[arr[i]] = true; } for (var key in obj) { ret_arr.push(key); } return ret_arr; }

Vanilla JS: elimine los duplicados mediante el seguimiento de los valores ya vistos (seguro para los pedidos)

O, para una versión segura de pedidos, use un objeto para almacenar todos los valores vistos anteriormente, y verifique los valores antes de agregarlos a una matriz.

function remove_duplicates_safe(arr) { var seen = {}; var ret_arr = []; for (var i = 0; i < arr.length; i++) { if (!(arr[i] in seen)) { ret_arr.push(arr[i]); seen[arr[i]] = true; } } return ret_arr; }

ECMAScript 6: Utilice la nueva estructura de datos del conjunto (seguro para los pedidos)

ECMAScript 6 agrega la nueva estructura de datos de Set , que le permite almacenar valores de cualquier tipo. Set.values devuelve elementos en orden de inserción.

function remove_duplicates_es6(arr) { let s = new Set(arr); let it = s.values(); return Array.from(it); }

Ejemplo de uso:

a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]; b = remove_duplicates(a); // b: // ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"] c = remove_duplicates_safe(a); // c: // ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"] d = remove_duplicates_es6(a); // d: // ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]


Además de ser una solución más simple y concisa que las respuestas actuales (menos las ES6 de futuro), probé esto y fue mucho más rápido también:

var uniqueArray = dupeArray.filter(function(item, i, self){ return self.lastIndexOf(item) == i; });

Se agregó una advertencia: Array.lastIndexOf () en IE9, por lo que si necesita ir más bajo, deberá buscar en otra parte.


Así que las opciones son:

let a = [11,22,11,22]; let b = [] b = [ ...new Set(a) ]; // b = [11, 22] b = Array.from( new Set(a)) // b = [11, 22] b = a.filter((val,i)=>{ return a.indexOf(val)==i }) // b = [11, 22]


Esta fue solo otra solución pero diferente al resto.

function diffArray(arr1, arr2) { var newArr = arr1.concat(arr2); newArr.sort(); var finalArr = []; for(var i = 0;i<newArr.length;i++) { if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) { finalArr.push(newArr[i]); } } return finalArr; }



Aquí es muy simple para entender y trabajar en cualquier lugar (incluso en PhotoshopScript) el código. ¡Revisalo!

var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"); peoplenames = unique(peoplenames); alert(peoplenames); function unique(array){ var len = array.length; for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++) if(array[j] == array[i]){ array.splice(j,1); j--; len--; } return array; } //*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]


Las respuestas principales tienen una complejidad de O(n²), pero esto se puede hacer con solo O(n)usar un objeto como hash:

function getDistinctArray(arr) { var dups = {}; return arr.filter(function(el) { var hash = el.valueOf(); var isDup = dups[hash]; dups[hash] = true; return !isDup; }); }

Esto funcionará para cadenas, números y fechas. Si su matriz contiene objetos complejos (es decir, deben compararse con ===), la solución anterior no funcionará. Puede obtener una O(n)implementación para los objetos estableciendo un indicador en el propio objeto:

function getDistinctObjArray(arr) { var distinctArr = arr.filter(function(el) { var isDup = el.inArray; el.inArray = true; return !isDup; }); distinctArr.forEach(function(el) { delete el.inArray; }); return distinctArr; }


$(document).ready(function() { var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"] var arr2=["cat","fish","mango","apple"] var uniquevalue=[]; var seconduniquevalue=[]; var finalarray=[]; $.each(arr1,function(key,value){ if($.inArray (value,uniquevalue) === -1) { uniquevalue.push(value) } }); $.each(arr2,function(key,value){ if($.inArray (value,seconduniquevalue) === -1) { seconduniquevalue.push(value) } }); $.each(uniquevalue,function(ikey,ivalue){ $.each(seconduniquevalue,function(ukey,uvalue){ if( ivalue == uvalue) { finalarray.push(ivalue); } }); }); alert(finalarray); });


for (i=0; i<originalArray.length; i++) { if (!newArray.includes(originalArray[i])) { newArray.push(originalArray[i]); } }