Obtenga todos los valores no únicos (es decir, duplicados / más de una aparición) en una matriz

418

Necesito verificar una matriz de JavaScript para ver si hay valores duplicados. ¿Cuál es la forma más fácil de hacer esto? Solo necesito encontrar cuáles son los valores duplicados: en realidad no necesito sus índices o cuántas veces se duplican.

Sé que puedo recorrer la matriz y verificar todos los demás valores para una coincidencia, pero parece que debería haber una manera más fácil.

Pregunta similar:

Scott Saunders
fuente
22
Parece haber años de confusión sobre lo que esta pregunta hace. Necesitaba saber qué elementos de la matriz estaban duplicados: "Solo necesito encontrar cuáles son los valores duplicados". La respuesta correcta NO debe eliminar duplicados de la matriz. Eso es lo contrario de lo que quería: una lista de los duplicados, no una lista de elementos únicos.
Scott Saunders

Respuestas:

302

Puede ordenar la matriz y luego ejecutarla y luego ver si el índice siguiente (o anterior) es el mismo que el actual. Suponiendo que su algoritmo de clasificación sea bueno, esto debería ser menor que O (n 2 ):

const findDuplicates = (arr) => {
  let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
  // JS by default uses a crappy string compare.
  // (we use slice to clone the array so the
  // original array won't be modified)
  let results = [];
  for (let i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
      results.push(sorted_arr[i]);
    }
  }
  return results;
}

let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

En el caso, si va a regresar como una función para duplicados. Esto es para un tipo similar de caso.

Referencia: https://stackoverflow.com/a/57532964/8119511

swilliams
fuente
10
"Asumiendo que su algoritmo de clasificación es bueno, esto debería ser menor que O ^ 2". Específicamente, podría ser O (n * log (n)).
ESRogs
83
Este script no funciona tan bien con más de 2 duplicados (por ejemploarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie
77
@swilliams No creo que esas pautas digan nada sobre no usar i++. En cambio, dicen que no escriban j = i + +j. Dos cosas diferentes en mi humilde opinión. Creo que i += 1es más confuso que lo simple y hermoso i++:)
Danilo Bargen
34
-1 Esta respuesta es incorrecta en muchos niveles. En primer lugar, var sorted_arr = arr.sort()es inútil: arr.sort()muta la matriz original (que es un problema en sí mismo). Esto también descarta un elemento. (Ejecute el código anterior. ¿Qué sucede con 9?) Cc @dystroy Una solución más limpia seríaresults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException
24
Todos: la pregunta pide mostrar los valores duplicados, no eliminarlos. No edite / rompa el código para intentar que haga algo que no está tratando de hacer. La alerta debe mostrar los valores que están duplicados.
Scott Saunders
205

Si desea eliminar los duplicados, pruebe esta excelente solución:

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

Fuente: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

rapfaria
fuente
18
Ese es un buen código, pero desafortunadamente no hace lo que estoy pidiendo.
Scott Saunders
67
El código anterior (que es mío, ese es mi blog) te acerca bastante. Un pequeño ajuste y ya estás allí. En primer lugar, puede ver si arr.length y out.length son iguales. Si son iguales, no hay elementos duplicados. Pero quieres un poco más. Si desea "atrapar" los engaños a medida que ocurren, verifique si la longitud de la matriz aumenta después de la línea obj [arr [i]] = 0. Ingenioso, ¿eh? :-) Gracias por las bonitas palabras, Raphael Montanaro.
Nosredna
66
@MarcoDemaio: Uh, no, ¿por qué el código no funcionaría con espacios? Puede poner lo que quiera en el nombre de una propiedad, simplemente no puede usar la sintaxis de puntos para acceder a los que tienen espacios (ni accesorios con varios otros caracteres que romperían el análisis).
Gijs
44
@Gijs: +1 tienes razón. No lo sabia. Pero todavía no funciona cuando se trata de una matriz de objetos.
Marco Demaio
3
Este algoritmo también tiene el efecto secundario de devolver una matriz ordenada, que podría no ser lo que desea.
asimétrico
166

Esta es mi respuesta del hilo duplicado (!):

Al escribir esta entrada 2014, todos los ejemplos fueron for-loops o jQuery. Javascript tiene las herramientas perfectas para esto: ordenar, asignar y reducir.

Encuentra artículos duplicados

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 duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)

console.log(duplicates) // [ 'Nancy' ]

Sintaxis más funcional:

@ Dmytro-Laptin señaló que se debe eliminar algún código. Esta es una versión más compacta del mismo código. Usando algunos trucos ES6 y funciones de orden superior:

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const count = names =>
  names.reduce((a, b) => ({ ...a,
    [b]: (a[b] || 0) + 1
  }), {}) // don't forget to initialize the accumulator

const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1)

console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))) // [ 'Nancy' ]

Christian Landgren
fuente
1
Este es el tipo de solución que he estado buscando. Si quisiera tener una docena de bucles for, sería bastante fácil de escribir. La palabra clave en el OP era "eficiente".
Josh
@ChristianLandgren, ¿dónde se declara la variable 'dict'? tal vez 'contar' debería usarse en su lugar?
Dmytro Laptin
44
Mantenga su opinión engañosa para usted (-1 por ser arrogante). Personalmente, estoy cansado de que las personas confundan "cortas" y "eficientes" y publiquen frases sin cuestionar las actuaciones. Los programas cortos y los JS modernos NO son mejores por naturaleza. Mal uso típico de la palabra "eficiente" aquí . Típica creencia ingenua aquí (lea los siguientes comentarios). Demostración aquí .
hoja
1
@leaf: mantenga sus sugerencias a sus propias respuestas. La solución que editó no es legible, puede ser rentable (probablemente no), pero aun así, la legibilidad a menudo es más importante que el rendimiento en mi opinión. Pero lo más importante: no elimine el código de otra persona para reemplazarlo con el suyo sin razón.
Christian Landgren
1
Diferentes respuestas, sí, diferentes opiniones, no lo creo.
hoja
64

Encuentra valores duplicados en una matriz

Esta debería ser una de las formas más cortas de encontrar valores duplicados en una matriz. Como lo solicitó específicamente el OP, esto no elimina los duplicados, sino que los encuentra .

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

Esto no necesita ordenación ni ningún marco de terceros. Tampoco necesita bucles manuales. Funciona con cada valor indexOf () (o para ser más claro: el operador de comparación estricta ) es compatible.

Debido a reduce () e indexOf () necesita al menos IE 9.

gripe
fuente
77
Flecha ES6 / versión simple / pura:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies
30

Puede agregar esta función, o modificarla y agregarla al prototipo de matriz de Javascript:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);
karim79
fuente
Esta es la mejor solución, pero tenga cuidado de agregarlo al prototipo de matriz, ya que eso dañará IE si recorre los valores.
Sampsa Suoninen
@RoyTinker perl también los admite, pero no tenía idea de que javascript lo hizo
Luke H
1
No hace lo que solicitó el OP, devuelve los duplicados.
RWC
27

ACTUALIZADO: Lo siguiente utiliza una estrategia combinada optimizada. Optimiza las búsquedas primitivas para beneficiarse del tiempo de búsqueda hash O (1) (la ejecución uniqueen una matriz de primitivas es O (n)). Las búsquedas de objetos se optimizan etiquetando objetos con una identificación única mientras se itera, por lo que identificar objetos duplicados también es O (1) por elemento y O (n) para toda la lista. La única excepción son los elementos que están congelados, pero son raros y se proporciona un respaldo mediante una matriz e indexOf.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

Si tiene Colecciones ES6 disponibles, entonces hay una versión mucho más simple y significativamente más rápida. (calce para IE9 + y otros navegadores aquí: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}

fuente
¿De Verdad? ¿Por qué responder una pregunta que se resolvió hace más de 2 años?
Rene Pot
3
Estaba respondiendo otra pregunta y aparentemente accidentalmente hice clic en alguien que se vinculaba con esta, llamándolo duplicado, y terminé clonando mi respuesta y confundiéndome muchísimo. Edito mis cosas mucho.
16
Creo que es bueno con diferentes soluciones. No importa que el tema sea antiguo y esté resuelto, ya que aún es posible encontrar diferentes formas de hacerlo. Es un problema típico en informática.
Emil Vikström
Es posible que desee mencionar que esto se basa en los métodos de matriz ES5 que no se implementan en IE <9.
Tim Down
24

ACTUALIZADO: una línea corta para obtener los duplicados:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

Para obtener la matriz sin duplicados, simplemente invierta la condición:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

Simplemente no pensé filter()en mi vieja respuesta a continuación;)


Cuando todo lo que necesita es verificar que no haya duplicados como se le preguntó en esta pregunta , puede usar el every()método:

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

Tenga en cuenta que every()no funciona para IE 8 y versiones inferiores.

Laurent Payot
fuente
1
No hace lo que solicitó el OP, devuelve los duplicados.
RWC
Es cierto, actualicé mi respuesta para arreglar eso.
Laurent Payot
Solución real! gracias
Jeremy Piednoel
21
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
Angel David Calderaro Pacciott
fuente
Esto parece funcionar, pero probablemente debería incluir algún texto que describa cómo funciona.
The DIMM Reaper
1
No funcionará si hay más 2 ocurrencias de un valor duplicado.
vasa
1
Esto es elegante y simple. Me encanta. Para aquellos que quieran descubrir cómo funcionan, he creado una esencia que muestra cómo mostrar duplicados y eliminar duplicados. Ver aquí: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Josh
@TheDIMMReaper para el segundo 'a'en la matriz, dentro de la función de filtro index == 1, mientras queself.indexOf('a') == 0
Sergiy Ostrovsky
19

Esto debería darte lo que quieres, solo los duplicados.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.
Daniel Beardsley
fuente
13

usando underscore.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}
Marco Allori
fuente
9

ES2015

//          🚩🚩   🚩                 🚩 
var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique;

// Combine all the arrays to a single one
unique = arr.concat(arr2, arr3)

// create a new (dirty) Array with only the unique items
unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' )

// Cleanup - remove duplicate & empty items items 
unique = [...new Set(unique)].filter(n => n)

console.log(unique)


Encuentre valores únicos de 3 matrices (o más):

Array.prototype.unique = function () {
    var arr = this.sort(), i; // input must be sorted for this to work
    for( i=arr.length; i--; )
      arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item

    return arr;
}

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,9],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    // merge arrays & call custom Array Prototype - "unique"
    unique = arr.concat(arr2, arr3).unique();

console.log(unique);  // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4]

Solo un polyfill para array indexOf para navegadores antiguos:

if (!Array.prototype.indexOf){
   Array.prototype.indexOf = function(elt /*, from*/){
     var len = this.length >>> 0;

     var from = Number(arguments[1]) || 0;
     from = (from < 0) ? Math.ceil(from) : Math.floor(from);
     if (from < 0)
        from += len;

     for (; from < len; from++){
        if (from in this && this[from] === elt)
           return from;
     }
     return -1;
  };
}

Solución jQuery usando "inArray":

if( $.inArray(this[i], arr) == -1 )

en lugar de agregar el Array.prototype.indexOf

vsync
fuente
+1 porque definitivamente es más legible el código usando Array.indexOf, pero desafortunadamente parece más lento que usar un simple bucle anidado. Incluso en navegadores que implementan Array.indexOf de manera ingeniosa como FF. Por favor, eche un vistazo a estas pruebas que hice aquí: jsperf.com/array-unique2 y hágame saber sus pensamientos.
Marco Demaio
@shekhardesigner - respuesta actualizada. "r" es la matriz en la que busca
vsync
@vsync Tuve que inicializar var r = [];para que tu código funcionara. Y funcionó a las mil maravillas.
Shekhar K. Sharma
@shekhardesigner: lo siento por la mezcla, para la solución Array Prototype no necesita una rvariable
vsync
2
No hace lo que solicitó el OP, devuelve los duplicados.
RWC
8

Aquí está mi solución simple y de una línea.

Primero no busca elementos únicos, luego hace que la matriz encontrada sea única con el uso de Set.

Entonces tenemos una serie de duplicados al final.

var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];

console.log([...new Set(
  array.filter((value, index, self) => self.indexOf(value) !== index))]
);

Oleg Abrazhaev
fuente
7

Esta es mi propuesta (ES6):

let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]

// b is now [1, 2, 4]
lukaszkups
fuente
1
Esto informará que una sola aparición de undefinedes un duplicado.
Dem Pilafian
1
@DemPilafian gracias, actualizado
lukaszkups
6
var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});

o cuando se agrega al prototyp.chain de Array

//copy and paste: without error handling
Array.prototype.unique = 
   function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}

Ver aquí: https://gist.github.com/1305056

Lorenz Lo Sauer
fuente
1
La función de filtro debe devolver verdadero o falso, no el elemento en sí. Filtrar una matriz que contenga 0 no los habría devuelto.
mflodin
Además, supongo que i&&es para evitar salir de los límites de la matriz, pero también significa que el primer elemento de la matriz ordenada no se incluirá. En su ejemplo no hay 1en la matriz resultante. Es decir, return i&&v!==o[i-1]?v:0;debe haberreturn v!==o[i-1];
mflodin
6

Manera rápida y elegante usando es6 objeto de desestructuración y reducción

Se ejecuta en O (n) (1 iteración sobre la matriz) y no repite valores que aparecen más de 2 veces

const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
  dup
} = arr.reduce(
  (acc, curr) => {
    acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
    if (acc.items[curr] === 2) acc.dup.push(curr)
    return acc
  }, {
    items: {},
    dup: []
  },
)

console.log(dup)
// ['hi', 'bye']

Lucas Janon
fuente
5

Aquí está la solución más simple que se me ocurre:

    const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']

    const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
    // => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]

    const duplicates = [...new Set(filtered)]

    console.log(duplicates)
    // => [ 2, 0, -1, 'a' ]

Eso es.

Nota:

  1. Funciona con cualquier número 0, incluidas cadenas y números negativos, por ejemplo -1: Pregunta relacionada: Obtener todos los valores únicos en una matriz de JavaScript (eliminar duplicados)

  2. La matriz original arrse conserva ( filterdevuelve la nueva matriz en lugar de modificar la original)

  3. La filteredmatriz contiene todos los duplicados; también puede contener más de 1 mismo valor (por ejemplo, nuestra matriz filtrada aquí es [ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. Si desea obtener solo valores duplicados (no desea tener múltiples duplicados con el mismo valor) puede usar [...new Set(filtered)](ES6 tiene un conjunto de objetos que puede almacenar solo valores únicos)

Espero que esto ayude.

Nikola Jovanovic
fuente
5

La vainilla más corta JS :

[1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]
pollos
fuente
4

Aquí hay una manera muy ligera y fácil:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}
Brandon Ferrara
fuente
La mejor respuesta. Y si el usuario desea una matriz de elementos duplicados, para esto actualicé el código @brandon var i = codes .length; var duplicate = []; while (i--) {if (codes .indexOf (codes [i])! = i) {if (duplicate.indexOf (codes [i]) === -1) {duplicate.push (arr [i]) ; } codes.splice (i, 1); }}
Himanshu Shekhar
4

Con ES6 (o usando Babel o typescipt) simplemente puede hacer:

var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);

https://es6console.com/j58euhbt/

Tocqueville
fuente
Llegué a la misma sintaxis, de forma independiente, y estaba a punto de agregarla como solución cuando encontré esta. Probablemente no sea el más económico, pero es simple.
nize
4

Código simple con sintaxis ES6 (devolver matriz ordenada de duplicados):

let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};

Cómo utilizar:

duplicates([1,2,3,10,10,2,3,3,10]);
invitado
fuente
1
.filter () sería mucho más simple
tocqueville
4

un trazador de líneas

var arr = [9,1,2,4,3,4,9]
console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates

sravan ganji
fuente
¿ indx!Qué hace para el primer ejemplo?
saylestyler
1
@saylestyler Jeje, esto significa indx !== ...- desigualdad estricta.
Daria
solo se agrega para una matriz de objetosresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix
4

Esta respuesta también puede ser útil, aprovecha el reduce operador / método js para eliminar duplicados de la matriz.

const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);

console.log(result);

Divyanshu Rawat
fuente
3
ahora podemos hacer new Set([1, 2, 2, 3, 3, 3, 3])para eliminar duplicados
kimbaudi
3

La siguiente función (una variación de la función deleteDuplicates ya mencionada) parece hacer el truco, devolviendo test2,1,7,5 para la entrada ["test", "test2", "test2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

Tenga en cuenta que el problema es más extraño en JavaScript que en la mayoría de los otros idiomas, porque una matriz de JavaScript puede contener casi cualquier cosa. Tenga en cuenta que las soluciones que utilizan la ordenación pueden necesitar proporcionar una función de ordenación adecuada; todavía no he probado esa ruta.

Esta implementación particular funciona para (al menos) cadenas y números.

function findDuplicates(arr) {
    var i,
        len=arr.length,
        out=[],
        obj={};

    for (i=0;i<len;i++) {
        if (obj[arr[i]] != null) {
            if (!obj[arr[i]]) {
                out.push(arr[i]);
                obj[arr[i]] = 1;
            }
        } else {
            obj[arr[i]] = 0;            
        }
    }
    return out;
}
Nosredna
fuente
3

Solo ES5 (es decir, necesita un polyfill filter () para IE8 y versiones inferiores):

var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];

arrayToFilter.
    sort().
    filter( function(me,i,arr){
       return (i===0) || ( me !== arr[i-1] );
    });
Gotofritz
fuente
Me gusta esta solución simple. Sin embargo, si desea los duplicados, primero debe encontrar esos duplicados y luego hacer que la lista de duplicados sea única. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (function (me, i, arr) {return (i! == 0 ) && (me == arr [i-1]);}). filter (function (me, i, arr) {return (i === 0) || (me! == arr [i-1]) ;});
Greg
3

var arr = [2, 1, 2, 2, 4, 4, 2, 5];

function returnDuplicates(arr) {
  return arr.reduce(function(dupes, val, i) {
    if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
      dupes.push(val);
    }
    return dupes;
  }, []);
}

alert(returnDuplicates(arr));

Esta función evita el paso de clasificación y utiliza el método reduce () para enviar duplicados a una nueva matriz si aún no existe.

vasa
fuente
3

Esta es probablemente una de las formas más rápidas de eliminar permanentemente los duplicados de una matriz 10 veces más rápido que la mayoría de las funciones aquí. Y 78 veces más rápido en safari

function toUnique(a,b,c){//array,placeholder,placeholder
 b=a.length;
 while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
toUnique(array);
console.log(array);
  1. Prueba: http://jsperf.com/wgu
  2. Demostración: http://jsfiddle.net/46S7g/
  3. Más: https://stackoverflow.com/a/25082874/2450730

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

EDITAR Como se indica en los comentarios, esta función devuelve una matriz con elementos únicos, sin embargo, la pregunta pide encontrar los duplicados. en ese caso, una simple modificación a esta función permite insertar los duplicados en una matriz, luego, al usar la función anterior, se toUniqueeliminan los duplicados de los duplicados.

function theDuplicates(a,b,c,d){//array,placeholder,placeholder
 b=a.length,d=[];
 while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1))
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

toUnique(theDuplicates(array));
coco
fuente
77
"si no puede leer el código anterior, pregunte, lea un libro de JavaScript" Hay demasiado código de golf en esta respuesta. Nombrar las variables como a, b, c hace que el código sea difícil de leer. Renunciar a las llaves se empeora aún más.
River-Claire Williamson
La mayoría de mis respuestas se basan en el rendimiento y el ahorro de espacio (otras soluciones ya están publicadas) ... si no le gusta hacer un voto negativo ... de lo contrario, aprenda JavaScript, lea un libro js ... o use jquery ... tiene muchas más respuestas si busca una solución simple. Si realmente quiere aprender algo, me complace explicar el código letra por letra. Como no puedo ver una pregunta real en su comentario, supongo que solo está buscando un motivo para rechazar mi respuesta ... continúe ... no tengo ningún problema con eso. Haga una pregunta real o dígame algo que no funcione con mi código.
cocco
99
No hay nada técnicamente incorrecto con su código. Dicho esto, nombrar las variables a, b, c, d, etc. y encadenar mientras los bucles dificultan la lectura del código. Entonces, el código no puede enseñar nada.
River-Claire Williamson
3

Usando "incluye" para probar si el elemento ya existe.

var arr = [1, 1, 4, 5, 5], darr = [], duplicates = [];

for(var i = 0; i < arr.length; i++){
  if(darr.includes(arr[i]) && !duplicates.includes(arr[i]))
    duplicates.push(arr[i])
  else
    darr.push(arr[i]);
}

console.log(duplicates);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>

Srichakradhar
fuente
El código devuelve elementos distintos, pero no conduce al resultado dado. Proporcione el código correcto completo.
RWC
3

ES6 ofrece la estructura de datos Set, que es básicamente una matriz que no acepta duplicados. Con la estructura de datos Set, hay una manera muy fácil de encontrar duplicados en una matriz (usando solo un bucle).

Aquí está mi código

function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
  for (let i = 0; i< arr.length; i++) {
     var size = set.size;
     set.add(arr[i]);
     if (set.size === size) {
         duplicates.add(arr[i]);
     }
  }
 return duplicates;
}
Roysh
fuente
3

Acabo de descubrir una manera simple de lograr esto usando un filtro de matriz

    var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    
    // Filter 1: to find all duplicates elements
    var duplicates = list.filter(function(value,index,self) {
       return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
    });
    
    console.log(duplicates);

alaahd
fuente
3

Seguir la lógica será más fácil y rápido

// @Param:data:Array that is the source 
// @Return : Array that have the duplicate entries
findDuplicates(data: Array<any>): Array<any> {
        return Array.from(new Set(data)).filter((value) => data.indexOf(value) !== data.lastIndexOf(value));
      }

Ventajas:

  1. Línea única :-P
  2. Toda la estructura de datos incorporada ayuda a mejorar la eficiencia.
  3. Más rápido

Descripción de la lógica:

  1. Convertir a conjunto para eliminar todos los duplicados
  2. Iterando a través de los valores establecidos
  3. Con cada verificación de valor establecido en la matriz de origen para la condición "los valores del primer índice no es igual al último índice" ==> Luego se infiere como duplicado, de lo contrario es 'único'

Nota: los métodos map () y filter () son eficientes y más rápidos.

PranavKAndro
fuente
1
Probado esto ... muy rápido. y tiene sentido ... ojalá lo hubiera pensado
Michael Rhema