In Javascript, come posso verificare se un array ha valori duplicati?


95

Possibile duplicato: il
modo più semplice per trovare valori duplicati in un array javascript

Come posso verificare se un array ha valori duplicati?

Se alcuni elementi dell'array sono gli stessi, restituisce true. Altrimenti, restituisci false.

['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist

Si noti che non mi interessa trovare la duplicazione, voglio solo il risultato booleano se gli array contengono duplicazioni.



2
Non voglio che un elenco di duplicati venga rimosso. Voglio solo sapere vero o falso se un elenco contiene duplicati.
user847495

7
Questa domanda non è un duplicato. Poiché @ user847495 vuole semplicemente controllare se esistono duplicati, la soluzione è più veloce / più facile di quanto necessario per trovare tutte le occorrenze di duplicati. Ad esempio, puoi farlo: codr.io/v/bvzxhqm
alden

2
usando la sottolineatura , una tecnica semplicevar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram

4
Non un duplicato della domanda contrassegnata. Si prega di prestare attenzione prima di contrassegnare le domande come tali.
John Weisz

Risposte:


222

Se hai un ambiente ES2015 (al momento della stesura di questo articolo: io.js, IE11, Chrome, Firefox, WebKit di notte), allora funzionerà e sarà veloce (vale a dire O (n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

Se hai bisogno solo di valori stringa nell'array, funzionerà quanto segue:

function hasDuplicates(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}

Usiamo una "tabella hash" le valuesSoFarcui chiavi sono i valori che abbiamo visto finora nell'array. Facciamo una ricerca usando inper vedere se quel valore è già stato individuato; se è così, usciamo dal giro e torniamo true.


Se hai bisogno di una funzione che funzioni per qualcosa di più dei semplici valori di stringa, quanto segue funzionerà, ma non è altrettanto performante; è O (n 2 ) invece di O (n).

function hasDuplicates(array) {
    var valuesSoFar = [];
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (valuesSoFar.indexOf(value) !== -1) {
            return true;
        }
        valuesSoFar.push(value);
    }
    return false;
}

La differenza è semplicemente che usiamo un array invece di una tabella hash valuesSoFar, poiché le "tabelle hash" (cioè gli oggetti) di JavaScript hanno solo chiavi stringa. Ciò significa che perdiamo il tempo di ricerca O (1) di in, ottenendo invece un tempo di ricerca O (n) di indexOf.


3
Riguardo al primo esempio che hai fornito. La convalida non è esattamente il contrario? Se la tua funzione ha un nome hasDuplicates, dovrebbe controllare se le dimensioni del set si sono effettivamente ridotte durante il processo di casting, giusto? Pertanto l'operatore booleano dovrebbe essere !==e non===
Tim Daubenschütz

pls modifica. Non posso modificare perché non sto cambiando più di 6 caratteri.
Tim Daubenschütz

1
Secondo MDN IE11 non supporta il costruttore utilizzato nel primo esempio
adam77

La versione normale di JS restituisce trueil seguente array:[1, '1']
Kunal

Quindi "se hai solo bisogno di valori stringa nell'array" che precede la risposta.
Domenic

4

Un altro approccio (anche per gli elementi oggetto / array all'interno dell'array 1 ) potrebbe essere 2 :

function chkDuplicates(arr,justCheck){
  var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
  arrtmp.sort();
  while(len--){
   var val = arrtmp[len];
   if (/nul|nan|infini/i.test(String(val))){
     val = String(val);
    }
    if (tmp[JSON.stringify(val)]){
       if (justCheck) {return true;}
       dupes.push(val);
    }
    tmp[JSON.stringify(val)] = true;
  }
  return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true);                           //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true);                //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true);          //=> false
chkDuplicates([1,2,3,4,5,1,2]);                            //=> [1,2]
chkDuplicates([1,2,3,4,5]);                                //=> null

Guarda anche...

1 richiede un browser che supporti JSON o una libreria JSON in caso contrario.
2 modifica: la funzione ora può essere utilizzata per un semplice controllo o per restituire un array di valori duplicati


3
Problemi non-showstopper di cui vale la pena essere a conoscenza: 1) muta l'array originale da ordinare; 2) non distingue null, NaN, Infinity, +Infinity, e -Infinity; 3) gli oggetti sono considerati uguali se hanno le stesse proprietà, anche se hanno prototipi diversi.
Domenic

1
@Domenic: sì, avrei dovuto menzionarlo. Modificato per aggirare la mutazione dell'array originale.
KooiInc

@Domenic: corretto per null / NaN / [+/-] Infinity, vedere modifiche.
KooiInc

@Domenic: Issue 3) in realtà non è un problema per me, perché è esattamente quello che voglio. Non mi interessa il prototipo, solo i valori.
timore reverenziale

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.