Dalam Javascript, bagaimana cara memeriksa apakah suatu array memiliki nilai duplikat?

95

Kemungkinan Duplikat:
Cara termudah untuk menemukan nilai duplikat dalam larik javascript

Bagaimana cara memeriksa apakah sebuah array memiliki nilai duplikat?

Jika beberapa elemen dalam larik sama, kembalikan nilai true. Jika tidak, kembalikan false.

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

Perhatikan Saya tidak peduli tentang menemukan duplikasi, hanya menginginkan hasil Boolean apakah array berisi duplikasi.

pengguna847495
sumber
2
Saya tidak ingin daftar duplikat dihapus. Saya hanya ingin tahu benar atau salah jika daftar memiliki duplikat di dalamnya.
pengguna847495
7
Pertanyaan ini bukan duplikat. Karena @ user847495 hanya ingin memeriksa apakah ada duplikat, solusinya lebih cepat / mudah daripada yang diperlukan untuk menemukan semua kemunculan duplikat. Misalnya, Anda dapat melakukan ini: codr.io/v/bvzxhqm
alden
2
menggunakan garis bawah , teknik sederhanavar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram
4
Bukan duplikat dari pertanyaan yang ditandai. Harap perhatikan sebelum menandai pertanyaan seperti itu.
John Weisz

Jawaban:

223

Jika Anda memiliki lingkungan ES2015 (saat tulisan ini dibuat: io.js, IE11, Chrome, Firefox, WebKit nightly), maka berikut ini akan berfungsi, dan akan cepat (yaitu. O (n)):

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

Jika Anda hanya membutuhkan nilai string dalam array, berikut ini akan berfungsi:

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

Kami menggunakan "tabel hash" valuesSoFaryang kuncinya adalah nilai yang kami lihat dalam array sejauh ini. Kami melakukan pencarian menggunakan inuntuk melihat apakah nilai itu sudah terlihat; jika demikian, kita keluar dari loop dan kembali true.


Jika Anda memerlukan fungsi yang berfungsi untuk lebih dari sekadar nilai string, berikut ini akan berfungsi, tetapi tidak sebagai performant; itu O (n 2 ) bukan 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;
}

Perbedaannya hanyalah bahwa kita menggunakan array daripada tabel hash valuesSoFar, karena "tabel hash" JavaScript (yaitu objek) hanya memiliki kunci string. Ini berarti kita kehilangan waktu pencarian O (1) in, alih-alih mendapatkan waktu pencarian O (n) sebesar indexOf.

Domenik
sumber
3
Tentang contoh pertama yang Anda berikan. Bukankah validasinya justru sebaliknya? Jika fungsi Anda dinamai hasDuplicates, maka itu harus memeriksa apakah ukuran set benar-benar menyusut selama proses casting, bukan? Oleh karena itu operator boolean harus !==dan tidak===
Tim Daubenschütz
tolong edit. Saya tidak dapat mengedit karena saya tidak mengubah lebih dari 6 karakter.
Tim Daubenschütz
1
Menurut MDN IE11 tidak mendukung konstruktor yang digunakan pada contoh pertama
adam77
Versi JS normal kembali trueuntuk larik berikut:[1, '1']
Kunal
Jadi "jika Anda hanya membutuhkan nilai string dalam array" sebelum jawabannya.
Domenic
4

Pendekatan lain (juga untuk elemen objek / larik dalam larik 1 ) bisa menjadi 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

Lihat juga...

1 memerlukan browser yang mendukung JSON, atau perpustakaan JSON jika tidak.
2 edit: function sekarang dapat digunakan untuk pemeriksaan sederhana atau untuk mengembalikan array nilai duplikat

KooiInc
sumber
3
Masalah non-showstopper yang perlu diperhatikan: 1) memutasikan larik asli yang akan diurutkan; 2) tidak membedakan antara null, NaN, Infinity, +Infinity, dan -Infinity; 3) objek dianggap sama jika mereka memiliki properti-sendiri yang sama, meskipun mereka memiliki prototipe yang berbeda.
Domenic
1
@Domenic: ya, seharusnya menyebutkannya. Diedit untuk menghindari mutasi larik asli.
KooiInc
@Domenic: dikoreksi untuk null / NaN / [+/-] Infinity, lihat edit.
KooiInc
@Domenic: Issue 3) sebenarnya bukan masalah bagi saya, karena itulah yang saya inginkan. Saya tidak peduli dengan prototipe, hanya nilainya.
kagum