Apa cara paling ringkas dan efisien untuk mengetahui apakah array JavaScript berisi nilai?
Ini adalah satu-satunya cara saya tahu untuk melakukannya:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Apakah ada cara yang lebih baik dan lebih ringkas untuk mencapai ini?
Ini sangat terkait dengan pertanyaan Stack Overflow Cara terbaik untuk menemukan item dalam JavaScript Array? yang membahas menemukan objek dalam array menggunakan indexOf
.
~[1,2,3].indexOf(4)
akan mengembalikan 0 yang akan bernilai false, sedangkan~[1,2,3].indexOf(3)
akan mengembalikan -3 yang akan dievaluasi sebagai benar.~
bukan apa yang ingin Anda gunakan untuk mengkonversi ke boolean, untuk itu Anda butuhkan!
. Tetapi dalam hal ini Anda ingin memeriksa kesetaraan dengan -1, sehingga fungsi mungkin berakhirreturn [1,2,3].indexOf(3) === -1;
~
adalah bukan biner, itu akan membalikkan setiap bit dari nilai secara individual.[1,2,3].indexOf(4)
sebenarnya akan mengembalikan -1 . Seperti @mcfedr tunjukkan,~
adalah operator bitwise-NOT , lihat ES5 11.4.8. Masalahnya, karena representasi biner-1
hanya terdiri dari 1, komplemennya adalah0
, yang dievaluasi sebagai false. Komplemen dari nomor lain akan menjadi nol, karenanya benar. Jadi,~
berfungsi dengan baik dan sering digunakan bersamaanindexOf
.[[1,2],[3,4]].includes([3,4])
?Jawaban:
Peramban modern memiliki
Array#includes
, yang melakukan hal itu dan didukung secara luas oleh semua orang kecuali IE:Anda juga dapat menggunakan
Array#indexOf
, yang kurang langsung, tetapi tidak memerlukan polyfill untuk browser yang sudah ketinggalan zaman.Banyak kerangka kerja juga menawarkan metode serupa:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
(juga alias_.include
dan_.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
(adalah_.contains
sebelum 4.0.0)R.includes(value, array)
Perhatikan bahwa beberapa kerangka kerja menerapkan ini sebagai fungsi, sementara yang lain menambahkan fungsi ke prototipe array.
sumber
Array.include
yang mengembalikan booleanarray.indexOf(object) != -1
inArray
adalah nama yang mengerikan untuk fungsi yang mengembalikan indeks elemen, dan-1
jika itu tidak ada. Saya harapkan boolean dikembalikan.Pembaruan dari 2019: Jawaban ini dari 2008 (11 tahun!) Dan tidak relevan untuk penggunaan JS modern. Peningkatan kinerja yang dijanjikan didasarkan pada tolok ukur yang dilakukan di browser saat itu. Mungkin tidak relevan dengan konteks eksekusi JS modern. Jika Anda membutuhkan solusi yang mudah, cari jawaban lain. Jika Anda membutuhkan kinerja terbaik, patok untuk diri sendiri di lingkungan eksekusi yang relevan.
Seperti yang orang lain katakan, iterasi melalui array mungkin adalah cara terbaik, tetapi telah terbukti bahwa
while
loop yang menurun adalah cara tercepat untuk beralih di JavaScript. Jadi, Anda mungkin ingin menulis ulang kode Anda sebagai berikut:Tentu saja, Anda juga dapat memperpanjang prototipe Array:
Dan sekarang Anda cukup menggunakan yang berikut ini:
sumber
for (o in array)
yang seharusnya tidak dilakukan ketika perulangan melalui array umumnya ...indexOf
mungkin, tetapi ini adalah "ekstensi JavaScript ke standar ECMA-262; karena itu mungkin tidak ada dalam implementasi standar lainnya."Contoh:
AFAICS Microsoft tidak menawarkan semacam alternatif untuk ini, tetapi Anda dapat menambahkan fungsionalitas serupa ke array di Internet Explorer (dan browser lain yang tidak mendukung
indexOf
) jika Anda ingin, sebagai diungkapkan oleh pencarian Google cepat (misalnya, yang ini ).sumber
ECMAScript 7 memperkenalkan
Array.prototype.includes
.Dapat digunakan seperti ini:
Ia juga menerima argumen opsional kedua
fromIndex
:Tidak seperti
indexOf
, yang menggunakan Strict Equality Comparison ,includes
membandingkan menggunakan algoritma kesetaraan SameValueZero . Itu berarti bahwa Anda dapat mendeteksi jika array menyertakanNaN
:Juga tidak seperti
indexOf
,includes
tidak melewatkan indeks yang hilang:Saat ini masih berupa konsep tetapi dapat di- polyfill agar berfungsi di semua browser.
sumber
Jawaban teratas mengasumsikan tipe primitif tetapi jika Anda ingin mengetahui apakah array berisi objek dengan beberapa sifat, Array.prototype.some () adalah solusi yang sangat elegan:
Yang menyenangkan tentang itu adalah bahwa iterasi dibatalkan setelah elemen ditemukan sehingga siklus iterasi yang tidak perlu terhindar.
Juga, itu sangat cocok dalam sebuah
if
pernyataan karena mengembalikan boolean:* Seperti yang ditunjukkan oleh jamess dalam komentar, pada saat jawaban ini, September 2018,
Array.prototype.some()
didukung penuh: tabel dukungan caniuse.comsumber
Arrow functions
dalam contoh ini tidak didukung dengan baik. Untuk detail lebih lanjut lihat di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Katakanlah Anda telah mendefinisikan array seperti:
Di bawah ini adalah tiga cara untuk memeriksa apakah ada
3
di sana. Semuanya kembalitrue
ataufalse
.Metode Array Asli (sejak ES2016) ( tabel kompatibilitas )
Sebagai metode Array khusus (sebelum ES2016)
Fungsi sederhana
sumber
Inilah implementasi JavaScript 1.6 yang kompatibel dari
Array.indexOf
:sumber
[].indexOf
adalah singkatan untukArray.prototype.indexOf
. Kami programmer Javascript paranoid-defensif menghindari memperluas prototipe asli di semua biaya.[].indexOf
membuat array baru lalu mengaksesindexOf
, sementaraArray.prototype.indexOf
hanya mengakses prototipe secara langsung?[].indexOf === Array.prototype.indexOf
(coba di FireBug), tetapi sebaliknya[].indexOf !== Array.indexOf
.Menggunakan:
sumber
x ? true : false
biasanya berlebihan. Ini di sini.array.indexOf(search) >= 0
sudah menjadi boolean. Adilreturn array.indexOf(search) >= 0
.Memperluas
Array
objek JavaScript adalah ide yang sangat buruk karena Anda memperkenalkan properti baru (metode khusus Anda) ke dalamfor-in
loop yang dapat memecah skrip yang ada. Beberapa tahun yang lalu penulis Prototipe perpustakaan harus merekayasa ulang implementasi perpustakaan mereka untuk menghapus hal semacam ini.Jika Anda tidak perlu khawatir tentang kompatibilitas dengan JavaScript lain yang berjalan di halaman Anda, coba, jika tidak, saya akan merekomendasikan solusi fungsi berdiri bebas yang lebih aneh, tapi lebih aman.
sumber
Satu-liner:
sumber
array.filter(e=>e==x).length > 0
setara denganarray.some(e=>e==x)
tetapisome
lebih efisienBerpikir di luar kotak sejenak, jika Anda melakukan panggilan ini berkali-kali, jauh lebih efisien untuk menggunakan
array asosiatifPeta untuk melakukan pencarian menggunakan fungsi hash.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
sumber
Saya menggunakan yang berikut ini:
sumber
Array.prototype.some () ditambahkan ke standar ECMA-262 di edisi ke-5
sumber
contains = (a, obj) => a.some((element) => element === obj))
Dua arah
indexOf
/lastIndexOf
alternatif semoga lebih cepat2015
Meskipun metode baru termasuk sangat bagus, dukungan pada dasarnya nol untuk saat ini.
Sudah lama saya memikirkan cara untuk mengganti fungsi indexOf / lastIndexOf yang lambat.
Cara performan telah ditemukan, dengan melihat jawaban teratas. Dari yang saya pilih
contains
fungsi diposting oleh @Damir Zekic yang seharusnya menjadi yang tercepat. Tapi itu juga menyatakan bahwa tolok ukur berasal dari 2008 dan sudah usang.Saya juga lebih suka
while
lebihfor
, tetapi karena tidak alasan tertentu saya berakhir menulis fungsi dengan untuk loop. Bisa juga dilakukan dengan awhile --
.Saya ingin tahu apakah iterasi jauh lebih lambat jika saya memeriksa kedua sisi array saat melakukannya. Tampaknya tidak, dan fungsi ini sekitar dua kali lebih cepat daripada yang terpilih. Jelas itu juga lebih cepat daripada yang asli. Ini di lingkungan dunia nyata, di mana Anda tidak pernah tahu apakah nilai yang Anda cari ada di awal atau di akhir array.
Ketika Anda tahu Anda baru saja mendorong array dengan sebuah nilai, menggunakan lastIndexOf mungkin merupakan solusi terbaik, tetapi jika Anda harus melakukan perjalanan melalui array besar dan hasilnya bisa di mana-mana, ini bisa menjadi solusi yang solid untuk membuat segalanya lebih cepat.
Bidirectional indexOf / lastIndexOf
Uji kinerja
http://jsperf.com/bidirectionalindexof
Sebagai tes saya membuat array dengan entri 100 ribu.
Tiga pertanyaan: di awal, di tengah & di akhir array.
Saya harap Anda juga menemukan ini menarik dan menguji kinerjanya.
Catatan: Seperti yang Anda lihat saya sedikit memodifikasi
contains
fungsi untuk mencerminkan indexOf & lastIndexOf output (jadi pada dasarnyatrue
denganindex
danfalse
dengan-1
). Itu seharusnya tidak merusaknya.Varian prototipe array
Fungsi ini juga dapat dengan mudah dimodifikasi untuk mengembalikan true atau false atau bahkan objek, string atau apa pun itu.
Dan inilah
while
variannya:Bagaimana ini mungkin?
Saya pikir perhitungan sederhana untuk mendapatkan indeks yang direfleksikan dalam array sangat sederhana sehingga dua kali lebih cepat daripada melakukan iterasi loop yang sebenarnya.
Berikut ini adalah contoh kompleks yang melakukan tiga pemeriksaan per iterasi, tetapi ini hanya mungkin dilakukan dengan perhitungan yang lebih lama yang menyebabkan pelambatan kode.
http://jsperf.com/bidirectionalindexof/2
sumber
Performa
Hari ini 2020.01.07 saya melakukan tes pada MacOs HighSierra 10.13.6 di Chrome v78.0.0, Safari v13.0.4 dan Firefox v71.0.0 untuk 15 solusi yang dipilih. Kesimpulan
JSON
,Set
dan secara mengejutkanfind
(K, N, O) paling lambat di semua browserincludes
(F) hanya cepat pada chromefor
(C, D) danindexOf
(G, H) cukup cepat pada semua browser pada array kecil dan besar jadi mungkin mereka adalah pilihan terbaik untuk solusi yang efisienfor
(C, D, E) memberikan hasil yang sama (~ 630 ops / detik - tetapi E pada safari dan firefox adalah 10- 20% lebih lambat dari C dan D)Hasil
Detail
Saya melakukan 2 tes kasus: untuk array dengan 10 elemen, dan array dengan 1 juta elemen. Dalam kedua kasus kami menempatkan elemen yang dicari di tengah array.
Tampilkan cuplikan kode
Array kecil - 10 elemen
Anda dapat melakukan tes di mesin Anda DI SINI
Array besar - 1.000.000 elemen
Anda dapat melakukan tes di mesin Anda DI SINI
sumber
Jika Anda menggunakan JavaScript 1.6 atau lebih baru (Firefox 1.5 atau lebih baru) Anda dapat menggunakan Array.indexOf . Kalau tidak, saya pikir Anda akan berakhir dengan sesuatu yang mirip dengan kode asli Anda.
sumber
Mengembalikan indeks array jika ditemukan, atau -1 jika tidak ditemukan
sumber
Kami menggunakan cuplikan ini (berfungsi dengan objek, array, string):
Pemakaian:
sumber
Jika Anda memeriksa berulang kali untuk keberadaan suatu objek dalam array Anda mungkin harus melihat ke dalamnya
contains(a, obj)
.sumber
Solusi yang bekerja di semua browser modern:
Pemakaian:
Solusi IE6 +:
Pemakaian:
Mengapa harus menggunakan
JSON.stringify
?Array.indexOf
danArray.includes
(juga sebagian besar jawaban di sini) hanya membandingkan dengan referensi dan bukan dengan nilai.Bonus
ES6 satu-liner yang tidak dioptimalkan:
Catatan: Membandingkan objek berdasarkan nilai akan bekerja lebih baik jika kunci berada dalam urutan yang sama, jadi agar aman Anda dapat mengurutkan kunci terlebih dahulu dengan paket seperti ini: https://www.npmjs.com/package/sort-keys
Memperbarui
contains
fungsi dengan optimasi perf. Terima kasih, keuangan karena menunjukkannya.sumber
includes
fungsi dengan saran Anda. Saya telah menjalankan jsperf dengan fungsi saya. Ini sekitar 5x lebih lambat dari termasuk lodash. Meskipun lodash tidak membandingkan dengan nilai dan tidak dapat menemukan{a: 1}
di[{a: 1}]
. Saya tidak tahu apakah ada perpustakaan yang melakukannya. Tapi saya ingin tahu apakah ada lebih banyak pemain dan tidak rumit cara melakukannya.contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
karena objek yang dirangkai mempertahankan urutan properti.sort-keys
catatan di bagian bawahGunakan beberapa fungsi lodash .
Ini ringkas, akurat dan memiliki dukungan lintas platform yang hebat.
Jawaban yang diterima bahkan tidak memenuhi persyaratan.
Persyaratan: Rekomendasikan cara yang paling ringkas dan efisien untuk mencari tahu apakah array JavaScript berisi objek.
Jawaban yang diterima:
Rekomendasi saya:
Catatan:
$ .inArray berfungsi dengan baik untuk menentukan apakah nilai skalar ada dalam array skalar ...
... tetapi pertanyaannya dengan jelas meminta cara yang efisien untuk menentukan apakah suatu objek terdapat dalam array.
Untuk menangani skalar dan objek, Anda bisa melakukan ini:
sumber
ECMAScript 6 memiliki proposal pencarian yang elegan.
Berikut adalah dokumentasi MDN tentang hal itu.
Fungsionalitas find berfungsi seperti ini.
Anda dapat menggunakan ini di ECMAScript 5 dan di bawahnya dengan mendefinisikan fungsi .
sumber
Meskipun
array.indexOf(x)!=-1
merupakan cara paling ringkas untuk melakukan ini (dan telah didukung oleh browser non-Internet Explorer selama lebih dari satu dekade ...), itu bukan O (1), melainkan O (N), yang mengerikan. Jika array Anda tidak akan berubah, Anda dapat mengubah array Anda menjadi hashtable, lalu lakukantable[x]!==undefined
atau===undefined
:Demo:
(Sayangnya, saat Anda dapat membuat Array.prototype.contain untuk "membekukan" array dan menyimpan hashtable di this._cache dalam dua baris, ini akan memberikan hasil yang salah jika Anda memilih untuk mengedit array Anda nanti. JavaScript memiliki kait yang tidak cukup untuk biarkan Anda mempertahankan status ini, tidak seperti Python misalnya.)
sumber
Satu dapat menggunakan Set yang memiliki metode "has ()":
sumber
return proxy.has(obj)
ini jauh lebih bersih daripada dua baris dengan pernyataan if-else di sinifunction contains(arr, obj) { return new Set(arr).has(obj); }
Menggunakan:
Demo
Untuk mengetahui apa yang
tilde
~
harus dilakukan pada saat ini, lihat pertanyaan ini Apa yang dilakukan tilde ketika mendahului ekspresi? .sumber
Oke, Anda bisa mengoptimalkan kode Anda untuk mendapatkan hasilnya!
Ada banyak cara untuk melakukan ini yang lebih bersih dan lebih baik, tetapi saya hanya ingin mendapatkan pola Anda dan menerapkannya dengan menggunakan
JSON.stringify
, cukup lakukan sesuatu seperti ini dalam kasus Anda:sumber
contains([{ a: 1, b: 2 }], { b: 2, a: 1 })
karena objek yang dirangkai mempertahankan urutan properti.Bukan berarti yang terbaik, tetapi saya hanya menjadi kreatif dan menambah repertoar.
Jangan gunakan ini
sumber
Terkejut bahwa pertanyaan ini masih belum memiliki sintaks terbaru yang ditambahkan, menambahkan 2 sen saya.
Katakanlah kita memiliki array Objects arrObj dan kami ingin mencari objek di dalamnya.
Array.prototype. indexOf -> ( indeks pengembalian atau -1 ) umumnya digunakan untuk menemukan indeks elemen dalam array. Ini juga dapat digunakan untuk mencari objek tetapi hanya berfungsi jika Anda memberikan referensi ke objek yang sama.
Array.prototype. termasuk -> (mengembalikan benar atau salah )
Array.prototype. find -> (mengambil callback, mengembalikan nilai / objek pertama yang mengembalikan true dalam CB).
Array.prototype. findIndex -> (mengambil callback, mengembalikan indeks nilai pertama / objek yang mengembalikan true dalam CB).
Karena menemukan dan menemukanIndex menerima panggilan balik, kita dapat mengambil objek apa pun (bahkan jika kita tidak memiliki referensi) dari array dengan secara kreatif mengatur kondisi sebenarnya.
sumber
Solusi sederhana untuk persyaratan ini digunakan
find()
Jika Anda memiliki berbagai objek seperti di bawah ini,
Kemudian Anda dapat memeriksa apakah objek dengan nilai Anda sudah ada atau belum
jika data nol maka tidak ada admin, selain itu akan mengembalikan objek yang ada seperti di bawah ini.
Kemudian Anda dapat menemukan indeks objek itu dalam array dan mengganti objek menggunakan kode di bawah ini.
Anda akan mendapatkan nilai seperti di bawah ini
Semoga ini bisa membantu siapa saja.
sumber
sumber