Javascript'te, bir dizinin yinelenen değerlere sahip olup olmadığını nasıl kontrol ederim?


95

Possible Duplicate:
Bir JavaScript dizisinde yinelenen değerleri bulmanın en kolay yolu

Bir dizinin yinelenen değerlere sahip olup olmadığını nasıl kontrol ederim?

Dizideki bazı öğeler aynıysa, true döndür. Aksi takdirde, yanlış döndür.

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

Çoğaltmayı bulmayı umursamıyorum, dizilerin yineleme içerip içermediğini yalnızca Boole sonucunu istiyorum.



2
Yinelenenlerin bir listesinin kaldırılmasını istemiyorum. Bir listede yinelenenler varsa doğru veya yanlışı bilmek istiyorum.
user847495

7
Bu soru kopya değil. @ User847495, kopyaların var olup olmadığını kontrol etmek istediğinden, çözüm, kopyaların tüm oluşumlarını bulmak için gerekenden daha hızlı / daha kolaydır. Örneğin, şunu yapabilirsiniz: codr.io/v/bvzxhqm
alden

2
alt çizgi kullanarak , basit teknikvar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram

4
İşaretlenen sorunun kopyası değil. Lütfen soruları bu şekilde işaretlemeden önce dikkatli olun.
John Weisz

Yanıtlar:


222

Bir ES2015 ortamınız varsa (bu yazı itibariyle: io.js, IE11, Chrome, Firefox, WebKit her gece), aşağıdakiler çalışacak ve hızlı olacaktır (yani O (n)):

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

Dizide yalnızca dize değerlerine ihtiyacınız varsa, aşağıdakiler çalışacaktır:

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

valuesSoFarAnahtarları dizide şimdiye kadar gördüğümüz değerler olan bir "hash tablosu" kullanıyoruz . Bu indeğerin zaten tespit edilip edilmediğini görmek için kullanarak bir arama yapıyoruz ; eğer öyleyse, döngüden kurtulur ve geri döneriz true.


Sadece dize değerlerinden daha fazlası için çalışan bir işleve ihtiyacınız varsa, aşağıdakiler çalışacaktır, ancak o kadar performanslı değildir; O (n ) yerine O (n 2 ).

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

Aradaki fark basitçe, valuesSoFarJavaScript "karma tabloları" (yani nesneler) yalnızca dize anahtarlarına sahip olduğundan, hash tablosu yerine bir dizi kullanmamızdır . Bu, O (1) arama süresini kaybettiğimiz anlamına gelir in, bunun yerine bir O (n) arama süresi elde ederiz indexOf.


3
Verdiğiniz ilk örnek hakkında. Doğrulama tam tersi değil mi? İşleviniz adlandırılmışsa hasDuplicates, kümenin boyutunun döküm işlemi sırasında gerçekten küçülüp küçülmediğini kontrol etmelidir, değil mi? Bu nedenle, boole operatörü olmalı !==ve olmamalıdır===
Tim Daubenschütz

lütfen düzenleyin. 6 karakterden fazlasını değiştirmediğim için düzenleme yapamıyorum.
Tim Daubenschütz

1
MDN'ye göre IE11, ilk örnekte kullanılan kurucuyu desteklemiyor
adam77

trueAşağıdaki dizi için normal JS sürümü döndürür :[1, '1']
Kunal

Böylece, yanıttan önce "dizide yalnızca dize değerlerine ihtiyacınız varsa".
Domenic

4

Diğer bir yaklaşım (ayrıca dizi 1 içindeki nesne / dizi öğeleri için ) 2 olabilir :

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

Ayrıca bakınız...

1 JSON'u destekleyen bir tarayıcıya veyadeğilsebir JSON kitaplığına ihtiyaç duyar.
2 düzenleme: işlev artık basit kontrol için veya yinelenen değerler dizisi döndürmek için kullanılabilir


3
Dikkat çekmeye değer, gösterişsiz olmayan sorunlar: 1) sıralanacak orijinal diziyi değiştirir; 2) arasında ayrım yapmaz null, NaN, Infinity, +Infinity, ve -Infinity; 3) Nesneler, farklı prototiplere sahip olsalar bile aynı kendi özelliklerine sahiplerse eşit kabul edilir.
Domenic

1
@Domenic: evet, bundan bahsetmeliydim. Orijinal dizinin mutasyonunu önlemek için düzenlendi.
KooiInc

@Domenic: null / NaN / [+/-] Infinity için düzeltildi, düzenlemelere bakın.
KooiInc

@Domenic: Sayı 3) aslında benim için sorun değil, çünkü tam olarak istediğim şey bu. Prototip umurumda değil, sadece değerler.
korku

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.