Jak w Javascript mogę sprawdzić, czy tablica ma zduplikowane wartości?

98

Możliwy duplikat:
Najłatwiejszy sposób na znalezienie zduplikowanych wartości w tablicy javascript

Jak sprawdzić, czy tablica ma zduplikowane wartości?

Jeśli niektóre elementy w tablicy są takie same, zwróć wartość true. W przeciwnym razie zwróć false.

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

Zauważ, że nie obchodzi mnie znajdowanie duplikatów, chcę tylko wyników boolowskich, czy tablice zawierają duplikaty.

user847495
źródło
2
Nie chcę usuwać listy duplikatów. Chcę tylko wiedzieć, czy lista zawiera duplikaty, czy prawda.
user847495,
7
To pytanie nie jest powtórzeniem. Ponieważ @ user847495 chce po prostu sprawdzić, czy istnieją duplikaty, rozwiązanie jest szybsze / łatwiejsze niż to, co jest potrzebne do znalezienia wszystkich wystąpień duplikatów. Na przykład możesz to zrobić: codr.io/v/bvzxhqm
alden
2
używając podkreślenia , prostej technikivar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram
4
To nie jest duplikat zaznaczonego pytania. Zwróć uwagę przed oznaczeniem pytań jako takich.
John Weisz

Odpowiedzi:

228

Jeśli masz środowisko ES2015 (w chwili pisania tego tekstu: io.js, IE11, Chrome, Firefox, WebKit nightly), poniższe będzie działać i będzie szybkie (a mianowicie O (n)):

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

Jeśli potrzebujesz tylko wartości ciągów w tablicy, zadziała:

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

Używamy „tablicy skrótów”, valuesSoFarktórej kluczami są wartości, które widzieliśmy do tej pory w tablicy. Sprawdzamy za pomocą, inaby sprawdzić, czy ta wartość została już wykryta; jeśli tak, wyjdziemy z pętli i wrócimy true.


Jeśli potrzebujesz funkcji, która działa dla więcej niż tylko wartości łańcuchowych, poniższe będą działać, ale nie są tak wydajne; to jest O (n 2 ) zamiast 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;
}

Różnica polega po prostu na tym, że używamy tablicy zamiast tablicy mieszającej valuesSoFar, ponieważ „tablice skrótów” JavaScript (tj. Obiekty) mają tylko klucze w postaci łańcuchów. Oznacza to, że tracimy czas wyszukiwania O (1) wynoszący in, zamiast tego uzyskujemy czas wyszukiwania O (n) wynoszący indexOf.

Domenic
źródło
3
O pierwszym przykładzie, który podałeś. Czy walidacja nie jest dokładnie odwrotna? Jeśli twoja funkcja jest nazwana hasDuplicates, to powinna sprawdzić, czy rozmiar zestawu faktycznie się zmniejszył podczas procesu jej rzutowania, prawda? Dlatego operator logiczny powinien być, !==a nie===
Tim Daubenschütz
pls edytuj. Nie mogę edytować, ponieważ nie zmieniam więcej niż 6 znaków.
Tim Daubenschütz
1
Według MDN IE11 nie obsługuje konstruktora zastosowanego w pierwszym przykładzie
adam77
1
Normalna wersja JS powraca truedla następującej tablicy:[1, '1']
Kunal
Tak więc „jeśli potrzebujesz tylko ciągów znaków w tablicy” poprzedzających odpowiedź.
Domenic
5

Innym podejściem (również w przypadku elementów obiektu / tablicy w tablicy 1 ) może być 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

Zobacz też...

1 wymaga przeglądarki obsługującej format JSON lub biblioteki JSON, jeśli nie.
2 edit: funkcja może być teraz używana do prostego sprawdzania lub zwracania tablicy zduplikowanych wartości

KooiInc
źródło
3
Zagadnienia niezwiązane z showstopperami, o których warto wiedzieć: 1) mutuje oryginalną tablicę do sortowania; 2) nie rozróżniać null, NaN, Infinity, +Infinityi -Infinity; 3) obiekty są uważane za równe, jeśli mają te same właściwości własne, nawet jeśli mają różne prototypy.
Domenic
1
@Domenic: tak, powinienem o tym wspomnieć. Edytowane w celu obejścia mutacji oryginalnej tablicy.
KooiInc,
@Domenic: poprawione na null / NaN / [+/-] Infinity, zobacz edycje.
KooiInc,
@Domenic: Issue 3) właściwie nie stanowi dla mnie problemu, ponieważ właśnie tego chcę. Nie obchodzi mnie prototyp, tylko wartości.
awe