En Javascript, comment vérifier si un tableau contient des valeurs en double?

95

Dupliquer possible:
moyen le plus simple de trouver des valeurs en double dans un tableau javascript

Comment vérifier si un tableau contient des valeurs en double?

Si certains éléments du tableau sont identiques, retournez true. Sinon, retournez false.

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

Remarquez que je ne me soucie pas de trouver la duplication, je veux seulement un résultat booléen si les tableaux contiennent des duplications.

user847495
la source
2
Je ne veux pas qu'une liste de doublons soit supprimée. Je veux juste savoir vrai ou faux si une liste contient des doublons.
user847495
7
Cette question n'est pas un doublon. Puisque @ user847495 veut simplement vérifier s'il existe des doublons, la solution est plus rapide / plus facile que ce qui est nécessaire pour trouver toutes les occurrences de doublons. Par exemple, vous pouvez faire ceci: codr.io/v/bvzxhqm
alden
2
utilisant un trait de soulignement , une technique simplevar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram
4
Pas un double de la question marquée. Veuillez faire attention avant de marquer les questions comme telles.
John Weisz le

Réponses:

222

Si vous avez un environnement ES2015 (au moment d'écrire ces lignes: io.js, IE11, Chrome, Firefox, WebKit tous les soirs), alors ce qui suit fonctionnera et sera rapide (à savoir O (n)):

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

Si vous n'avez besoin que de valeurs de chaîne dans le tableau, ce qui suit fonctionnera:

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

Nous utilisons une "table de hachage" valuesSoFardont les clés sont les valeurs que nous avons vues dans le tableau jusqu'à présent. Nous effectuons une recherche en utilisant inpour voir si cette valeur a déjà été repérée; si c'est le cas, nous sortons de la boucle et revenons true.


Si vous avez besoin d'une fonction qui fonctionne pour plus que de simples valeurs de chaîne, ce qui suit fonctionnera, mais n'est pas aussi performant; c'est O (n 2 ) au lieu de 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 différence est simplement que nous utilisons un tableau au lieu d'une table de hachage valuesSoFar, car les "tables de hachage" JavaScript (c'est-à-dire les objets) n'ont que des clés de chaîne. Cela signifie que nous perdons le temps de recherche O (1) de in, au lieu d'obtenir un temps de recherche O (n) de indexOf.

Domenic
la source
3
À propos du premier exemple que vous avez donné. La validation n'est-elle pas exactement l'inverse? Si votre fonction est nommée hasDuplicates, elle devrait vérifier si la taille de l'ensemble a effectivement diminué pendant le processus de conversion, n'est-ce pas? Par conséquent, l'opérateur booléen devrait être !==et non===
Tim Daubenschütz
pls modifier. Je ne peux pas modifier car je ne change pas plus de 6 caractères.
Tim Daubenschütz
1
Selon MDN IE11 ne prend pas en charge le constructeur utilisé dans le premier exemple
adam77
La version normale de JS revient truepour le tableau suivant:[1, '1']
Kunal
Ainsi "si vous n'avez besoin que de valeurs de chaîne dans le tableau" précédant la réponse.
Domenic
4

Une autre approche (également pour les éléments objet / tableau dans le tableau 1 ) pourrait être 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

Voir également...

1 nécessite un navigateur prenant en charge JSON, ou une bibliothèque JSON sinon.
2 edit: la fonction peut maintenant être utilisée pour une simple vérification ou pour renvoyer un tableau de valeurs en double

KooiInc
la source
3
Problèmes non-showstopper qui méritent d'être pris en compte: 1) mute le tableau d'origine à trier; 2) ne fait pas de distinction entre null, NaN, Infinity, +Infinity, et -Infinity; 3) les objets sont considérés comme égaux s'ils ont les mêmes propriétés propres, même s'ils ont des prototypes différents.
Domenic le
1
@Domenic: oui, j'aurais dû le mentionner. Modifié pour éviter la mutation de la matrice d'origine.
KooiInc
@Domenic: corrigé pour null / NaN / [+/-] Infinity, voir les modifications.
KooiInc le
@Domenic: Numéro 3) n'est en fait pas un problème pour moi, car c'est exactement ce que je veux. Je me fiche du prototype, juste des valeurs.
awe