Ottieni tutti i valori non univoci (ovvero: duplicato / più di un'occorrenza) in un array


418

Devo controllare un array JavaScript per vedere se ci sono valori duplicati. Qual è il modo più semplice per farlo? Devo solo trovare quali sono i valori duplicati: in realtà non ho bisogno dei loro indici o quante volte vengono duplicati.

So di poter eseguire il loop nell'array e controllare tutti gli altri valori per una corrispondenza, ma sembra che ci dovrebbe essere un modo più semplice.

Domanda simile:


22
Sembra che ci siano anni di confusione su ciò che questa domanda pone. Avevo bisogno di sapere quali elementi dell'array erano duplicati: "Devo solo trovare quali sono i valori duplicati". La risposta corretta NON deve rimuovere i duplicati dall'array. Questo è l'inverso di ciò che volevo: un elenco dei duplicati, non un elenco di elementi unici.
Scott Saunders,

Risposte:


302

È possibile ordinare l'array e quindi eseguirlo e quindi vedere se l'indice successivo (o precedente) è uguale all'attuale. Supponendo che il tuo algoritmo di ordinamento sia buono, questo dovrebbe essere inferiore a 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)}`);

Nel caso, se si desidera tornare come funzione per i duplicati. Questo è per un tipo simile di caso.

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


10
"Supponendo che il tuo algoritmo di ordinamento sia buono, dovrebbe essere inferiore a O ^ 2". In particolare, potrebbe essere O (n * log (n)).
ESRogs

83
Questo script non funziona così bene con più di 2 duplicati (ad esempioarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie,

7
@swilliams Non credo che queste linee guida dicano qualcosa sul non utilizzo i++. Invece, dicono di non scrivere j = i + +j. Due cose diverse IMHO. Penso che i += 1sia più confuso del semplice e bello i++:)
Danilo Bargen il

34
-1 Questa risposta è sbagliata su molti livelli. Innanzitutto var sorted_arr = arr.sort()è inutile: arr.sort()muta l'array originale (che è un problema a sé stante). Questo scarta anche un elemento. (Esegui il codice sopra. Cosa succede a 9?) Cc @dystroy Una soluzione più pulita sarebberesults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException

24
Tutti: la domanda chiede di visualizzare i valori duplicati, non di rimuoverli. Si prega di non modificare / rompere il codice per provare a farlo fare qualcosa che non sta cercando di fare. L'avviso dovrebbe mostrare i valori duplicati.
Scott Saunders,

205

Se vuoi eliminare i duplicati, prova questa ottima soluzione:

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;
}

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


18
Questo è un buon codice, ma sfortunatamente non fa quello che sto chiedendo.
Scott Saunders,

67
Il codice sopra (che è mio - questo è il mio blog) ti avvicina molto. Una piccola modifica e ci sei. Prima di tutto, puoi vedere se arr.length e out.length sono uguali. Se sono uguali, non ci sono elementi duplicati. Ma vuoi un po 'di più. Se si desidera "catturare" i duplicati quando si verificano, verificare se la lunghezza dell'array aumenta dopo la riga obj [arr [i]] = 0. Nifty, eh? Sorriso Grazie per le belle parole, Raphael Montanaro.
Nosredna,

6
@MarcoDemaio: Uh, no, perché il codice non dovrebbe funzionare con gli spazi? Puoi mettere quello che vuoi in un nome di proprietà - semplicemente non puoi usare la sintassi punto per accedere a quelli con spazi (né oggetti di scena con vari altri personaggi che interromperebbero l'analisi).
Gijs,

4
@Gijs: +1 hai ragione. Non lo sapevo. Ma non funziona ancora quando si tratta di una matrice di oggetti.
Marco Demaio,

3
Questo algoritmo ha anche l'effetto collaterale di restituire un array ordinato, che potrebbe non essere quello che desideri.
asimmetrico,

166

Questa è la mia risposta dal thread duplicato (!):

Quando scrivevo questa voce 2014, tutti gli esempi erano for-loop o jQuery. Javascript ha gli strumenti perfetti per questo: ordinare, mappare e ridurre.

Trova elementi duplicati

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' ]

Sintassi più funzionale:

@ Dmytro-Laptin ha sottolineato la rimozione di alcuni codici. Questa è una versione più compatta dello stesso codice. Utilizzando alcuni trucchi ES6 e funzioni di ordine superiore:

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' ]


1
Questo è il tipo di soluzione che stavo cercando. Se volessi avere una dozzina di loop-for, sarebbe abbastanza facile da scrivere. La parola chiave nel PO era "efficiente".
Josh,

@ChristianLandgren, dove viene dichiarata la variabile 'dict'? forse invece dovrebbe essere usato "count"?
Dmytro Laptin,

4
Tieni per te la tua opinione fuorviante (-1 per essere arrogante). Personalmente sono stanco delle persone che confondono "breve" ed "efficiente" e pubblicano una riga senza mettere in discussione le prestazioni. Programmi brevi e moderni JS NON sono migliori per natura. Tipico uso improprio della parola "efficiente" qui . Tipica convinzione ingenua qui (leggi i seguenti commenti). Demo qui .
foglia

1
@foglia - ti preghiamo di conservare i tuoi suggerimenti per le tue risposte. La soluzione che hai modificato non è leggibile, potrebbe essere performante (probabilmente no) ma anche così - la leggibilità spesso è più importante della performance secondo me. Ma soprattutto - non rimuovere il codice di qualcun altro per sostituirlo con il tuo senza motivo.
Christian Landgren,

1
Diverse risposte, sì, opinioni diverse, io non la penso così.
foglia

64

Trova valori duplicati in un array

Questo dovrebbe essere uno dei modi più brevi per trovare effettivamente valori duplicati in un array. Come specificamente richiesto dall'OP, ciò non rimuove i duplicati ma li trova .

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])

Questo non richiede ordinamento o alcun framework di terze parti. Inoltre non ha bisogno di loop manuali. Funziona con ogni valore indexOf () (o per essere più chiari: l' operatore di confronto rigoroso supportato da ).

A causa di reduce () e indexOf () ha bisogno almeno di IE 9.


7
Freccia ES6 / versione semplice / pura:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies

30

È possibile aggiungere questa funzione o modificarla e aggiungerla al prototipo dell'array di 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);

Questa è la soluzione migliore, ma fai attenzione ad aggiungerla al prototipo dell'array, poiché ciò rovinerà IE se eseguirà il ciclo tra i valori.
Sampsa Suoninen,

@RoyTinker perl supporta anche loro, ma non avevo idea che lo avesse fatto JavaScript
Luke H

1
Non fa ciò che l'OP ha richiesto, restituisce i duplicati.
RWC,

27

AGGIORNATO: Di seguito viene utilizzata una strategia combinata ottimizzata. Ottimizza le ricerche primitive per beneficiare del tempo di ricerca dell'hash O (1) (l'esecuzione uniquesu una matrice di primitive è O (n)). Le ricerche di oggetti sono ottimizzate codificando gli oggetti con un ID univoco durante l'iterazione, pertanto l'identificazione di oggetti duplicati è anche O (1) per elemento e O (n) per l'intero elenco. L'unica eccezione sono gli elementi che vengono congelati, ma quelli sono rari e viene fornito un fallback utilizzando un array e un 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;
}();

Se hai raccolte ES6 disponibili, esiste una versione molto più semplice e significativamente più veloce. (shim per IE9 + e altri browser qui: 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;
    }
  });
}

veramente? perché rispondere a una domanda che è stata risolta più di 2 anni fa?
Rene Pot,

3
Stavo rispondendo a un'altra domanda e apparentemente ho cliccato per sbaglio su qualcuno che si collegava a questo, chiamandolo un duplicato, e ho finito per clonare la mia risposta e confondermi l'inferno. Modifico molto le mie cose.


16
Penso che sia bello con diverse soluzioni. Non importa che l'argomento sia vecchio e risolto poiché è ancora possibile trovare diversi modi per farlo. È un problema tipico nell'informatica.
Emil Vikström,

Potresti voler dire che questo si basa su metodi di array ES5 che non sono implementati in IE <9.
Tim Down

24

AGGIORNATO: Short one-liner per ottenere i duplicati:

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

Per ottenere l'array senza duplicati basta invertire la condizione:

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

Semplicemente non ci ho pensato filter()nella mia vecchia risposta di seguito;)


Quando tutto ciò che serve è verificare che non vi siano duplicati come richiesto in questa domanda, è possibile utilizzare il every()metodo:

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

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

Si noti che every()non funziona per IE 8 e versioni precedenti.


1
Non fa ciò che l'OP ha richiesto, restituisce i duplicati.
RWC,

È vero, ho aggiornato la mia risposta per risolverlo.
Laurent Payot,

Soluzione reale! thnaks
Jeremy Piednoel,

21
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})

Questo sembra funzionare, ma probabilmente dovresti includere del testo che descriva come funziona.
Il DIMM Reaper

1
Non funzionerà se ci sono più 2 occorrenze di un valore duplicato.
Vasa,

1
Questo è elegante e semplice. Lo adoro. Per coloro che vogliono capire come funzionano, ho creato una sintesi che mostra come mostrare i duplicati ed eliminare i duplicati. Vedi qui: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Josh

@TheDIMMReaper per il secondo 'a'in array, funzione filtro interno index == 1, mentreself.indexOf('a') == 0
Sergiy Ostrovsky

19

Questo dovrebbe darti quello che vuoi, solo i duplicati.

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.

13

utilizzando underscore.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}

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)


Trova valori univoci da 3 array (o più):

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 per indice di array Di vecchi browser:

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;
  };
}

Soluzione jQuery usando "inArray":

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

invece di aggiungere il Array.prototype.indexOf


+1 perché è sicuramente più leggibile il codice usando Array.indexOf, ma sfortunatamente sembra più lento dell'uso di un semplice ciclo nidificato. Anche su browser che implementano Array.indexOf in modo strano come FF. Per favore, dai un'occhiata a questi test che ho fatto qui: jsperf.com/array-unique2 e fammi sapere i tuoi pensieri.
Marco Demaio,

@shekhardesigner - risposta aggiornata. "r" è l'array in cui cerchi
vsync,

@vsync Ho dovuto inizializzare, var r = [];per far funzionare il tuo codice. E ha funzionato come per incanto.
Shekhar K. Sharma,

@shekhardesigner - Mi dispiace per il mix, per la soluzione Array Prototype non hai bisogno di una rvariabile
vsync

2
Non fa ciò che l'OP ha richiesto, restituisce i duplicati.
RWC,

8

Ecco la mia soluzione semplice e a una riga.

Cerca prima gli elementi non univoci, quindi rende unico l'array trovato con l'uso di Set.

Quindi alla fine abbiamo una serie di duplicati.

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))]
);


7

Questa è la mia proposta (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]

1
Ciò segnalerà che una singola occorrenza di undefinedè un duplicato.
Dem Pilafian,

1
@DemPilafian grazie, aggiornato
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 quando aggiunto alla prototyp.chain di 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;});}

Vedi qui: https://gist.github.com/1305056


1
La funzione filtro dovrebbe restituire vero o falso, non l'elemento stesso. Il filtraggio di un array contenente 0 non li avrebbe restituiti.
mflodin,

Inoltre, suppongo che i&&sia per evitare di uscire dai limiti dell'array, ma significa anche che il primo elemento dell'array ordinato non verrà incluso. Nel tuo esempio non è presente 1nell'array risultante. Ie return i&&v!==o[i-1]?v:0;dovrebbe esserereturn v!==o[i-1];
mflodin

6

Modo rapido ed elegante con la distruzione e la riduzione degli oggetti es6

Funziona in O (n) (1 iterazione sull'array) e non ripete i valori che appaiono più di 2 volte

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']


5

Ecco la soluzione più semplice a cui potrei pensare:

    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' ]

Questo è tutto.

Nota:

  1. Funziona con qualsiasi numero incluso 0, stringhe e numeri negativi, ad es. -1- Domanda correlata: ottieni tutti i valori univoci in un array JavaScript (rimuovi duplicati)

  2. L'array originale arrviene conservato ( filterrestituisce il nuovo array invece di modificare l'originale)

  3. La filteredmatrice contiene tutti i duplicati; esso può anche contenere più di 1 stesso valore (es nostra matrice filtrata qui è [ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. Se si desidera ottenere solo valori duplicati (non si desidera avere più duplicati con lo stesso valore) è possibile utilizzare [...new Set(filtered)](ES6 ha un set di oggetti che può memorizzare solo valori univoci)

Spero che sia di aiuto.


5

Vaniglia JS più corta :

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

4

Ecco un modo molto leggero e semplice:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}

Migliore risposta. E se l'utente desidera una matrice di elementi duplicati, per questo ho aggiornato il codice @brandon var i = codes .length; var duplicate = []; while (i--) {if (codici .indexOf (codici [i])! = i) {if (duplicate.indexOf (codici [i]) === -1) {duplicate.push (arr [i]) ; } codes.splice (i, 1); }}
Himanshu Shekhar,

4

Con ES6 (o usando Babel o Typescipt) puoi semplicemente fare:

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

https://es6console.com/j58euhbt/


Sono arrivato alla stessa sintassi, indipendentemente, e stavo per aggiungerlo come soluzione quando ho trovato questo. Probabilmente non è il più economico, ma è semplice.
nize,

4

Codice semplice con sintassi ES6 (restituisce un array ordinato di duplicati):

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};

Come usare:

duplicates([1,2,3,10,10,2,3,3,10]);

1
.filter () sarebbe molto più semplice
tocqueville

4

una fodera

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


cosa fa indx!per il primo esempio?
saylestyler,

1
@saylestyler Hehe, questo significa indx !== ...- disuguaglianza rigorosa.
Daria,

aggiungendo solo per array di oggettiresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix,

4

Questa risposta potrebbe anche essere utile, sfrutta l' reduce operatore / metodo js per rimuovere i duplicati dall'array.

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

console.log(result);


3
ora possiamo semplicemente fare new Set([1, 2, 2, 3, 3, 3, 3])per rimuovere i duplicati
kimbaudi

3

La seguente funzione (una variante della funzione deleteDuplicates già menzionata) sembra fare il trucco, restituendo test2,1,7,5 per l'ingresso ["test", "test2", "test2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

Si noti che il problema è più strano in JavaScript che nella maggior parte delle altre lingue, perché un array JavaScript può contenere praticamente qualsiasi cosa. Tieni presente che le soluzioni che utilizzano l'ordinamento potrebbero dover fornire una funzione di ordinamento appropriata: non ho ancora provato questa strada.

Questa particolare implementazione funziona per (almeno) stringhe e numeri.

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;
}

3

Solo ES5 (ovvero, necessita di un polyfill filtro () per IE8 e versioni precedenti):

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] );
    });

Mi piace questa semplice soluzione. Se vuoi i duplicati, tuttavia, devi prima trovare quei duplicati e quindi rendere unico l'elenco dei duplicati. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (funzione (me, i, arr) {return (i! == 0 ) && (me == arr [i-1]);}). filter (funzione (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));

Questa funzione evita la fase di ordinamento e utilizza il metodo reduce () per inviare duplicati a un nuovo array se non esiste già in esso.


3

Questo è probabilmente uno dei modi più veloci per rimuovere definitivamente i duplicati da un array 10 volte più veloce rispetto alla maggior parte delle funzioni qui. 78 volte più veloce in 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. Test: http://jsperf.com/wgu
  2. Demo: http://jsfiddle.net/46S7g/
  3. Altro: https://stackoverflow.com/a/25082874/2450730

se non riesci a leggere il codice sopra chiedi, leggi un libro javascript o qui ci sono alcune spiegazioni sul codice più breve. https://stackoverflow.com/a/21353032/2450730

EDIT Come indicato nei commenti, questa funzione restituisce un array con univoci, tuttavia la domanda chiede di trovare i duplicati. in tal caso una semplice modifica a questa funzione consente di inserire i duplicati in un array, quindi l'utilizzo della funzione precedente toUniquerimuove i duplicati dei duplicati.

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));

7
"se non riesci a leggere il codice sopra chiedi, leggi un libro javascript" In questa risposta c'è del tutto troppo code golf. Denominare le variabili come a, b, c rende il codice difficile da leggere. Rinunciare alle parentesi graffe rende ancora peggio.
River-Claire Williamson,

La maggior parte delle mie risposte si basano su prestazioni e risparmio di spazio (altre soluzioni sono già pubblicate) ... se non ti piace downvote ... altrimenti impara javascript, leggi un js book ... o usa jquery ... loro hai molte più risposte se cerchi una soluzione semplice. Se vuoi davvero imparare qualcosa, sono felice di spiegare la lettera di codice per lettera. Dato che non riesco a vedere una vera domanda nel tuo commento, immagino che tu stia solo cercando un motivo per sottovalutare la mia risposta .... continua ... non ho problemi con quello. Fai una vera domanda o dimmi qualcosa che non funziona con il mio codice.
cocco,

9
Non c'è nulla di tecnicamente sbagliato nel tuo codice. Detto questo, nominare le variabili a, b, c, d, ecc. E concatenare mentre i loop rende difficile la lettura del codice. Quindi, il codice non riesce a insegnare nulla.
River-Claire Williamson,

3

L'uso di "include" per verificare se l'elemento esiste già.

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>


Il codice restituisce elementi distinti, ma non porta al risultato dato. Fornisci il codice corretto completo.
RWC,

3

ES6 offre la struttura di dati Set che è fondamentalmente un array che non accetta duplicati. Con la struttura dei dati Set, c'è un modo molto semplice per trovare duplicati in un array (usando solo un loop).

Ecco il mio codice

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;
}

3

Ho appena trovato un modo semplice per ottenere questo risultato usando un filtro Array

    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);


3

Seguire la logica sarà più facile e veloce

// @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));
      }

Vantaggi:

  1. Linea singola :-P
  2. Tutta la struttura di dati integrata che aiuta a migliorare l'efficienza
  3. Più veloce

Descrizione della logica:

  1. Conversione in set per rimuovere tutti i duplicati
  2. Scorrendo i valori impostati
  3. Con ogni valore impostato controllare nell'array di origine la condizione "valori primo indice non è uguale all'ultimo indice" ==> Quindi dedotto come duplicato altrimenti è 'unico'

Nota: i metodi map () e filter () sono efficienti e più veloci.


1
Ho provato questo ... molto velocemente. e ha senso .. vorrei averci pensato
Michael Rhema,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.