Saya ingin membandingkan dua array ... idealnya, efisien. Tidak ada yang mewah, hanya true
jika mereka identik, dan false
jika tidak. Tidak mengherankan, operator perbandingan sepertinya tidak berfungsi.
var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2); // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2)); // Returns true
JSON menyandikan setiap array, tetapi apakah ada cara yang lebih cepat atau "lebih baik" untuk hanya membandingkan array tanpa harus beralih melalui setiap nilai?
javascript
arrays
json
Julian H. Lam
sumber
sumber
([] == []) == false
.Jawaban:
Untuk membandingkan array, mengulanginya dan membandingkan setiap nilai:
Membandingkan array:
Pemakaian:
Anda mungkin berkata " Tetapi jauh lebih cepat untuk membandingkan string - tidak ada loop ... " baik, maka Anda harus mencatat ada loop. Loop rekursif pertama yang mengubah Array menjadi string dan kedua, yang membandingkan dua string. Jadi metode ini lebih cepat dari penggunaan string .
Saya percaya bahwa jumlah data yang lebih besar harus selalu disimpan dalam array, bukan pada objek. Namun jika Anda menggunakan objek, mereka dapat sebagian juga dibandingkan.
Begini caranya:
Membandingkan objek:
Saya telah menyatakan di atas, bahwa dua instance objek tidak akan pernah sama, bahkan jika mereka berisi data yang sama saat ini:
Ini memiliki alasan, karena mungkin ada, misalnya variabel pribadi dalam objek.
Namun, jika Anda hanya menggunakan struktur objek untuk memuat data, perbandingan masih dimungkinkan:
Namun, ingat bahwa ini adalah untuk melayani dalam membandingkan JSON seperti data, bukan instance kelas dan hal-hal lainnya. Jika Anda ingin membandingkan objek yang lebih rumit, lihat jawaban ini dan fungsinya sangat panjang .
Untuk membuatnya bekerja,
Array.equals
Anda harus sedikit mengedit fungsi aslinya:Saya membuat alat uji kecil untuk kedua fungsi .
Bonus: Arang bersarang dengan
indexOf
dancontains
Samy Bencherif telah menyiapkan fungsi yang berguna untuk kasus Anda mencari objek tertentu dalam array bersarang, yang tersedia di sini: https://jsfiddle.net/SamyBencherif/8352y6yw/
sumber
this[i] !== array[i]
bukan!=
.equals
bukancompare
. Setidaknya dalam .NET, bandingkan biasanya mengembalikan int yang ditandai yang menunjukkan objek mana yang lebih besar dari yang lain. Lihat: Pembanding . Bandingkan .Meskipun ini hanya berfungsi untuk array skalar (lihat catatan di bawah), ini singkat:
Rr, dalam ECMAScript 6 / CoffeeScript / TypeScript dengan Fungsi Panah:
(Catatan: 'skalar' di sini berarti nilai yang dapat dibandingkan secara langsung menggunakan
===
. Jadi: angka, string, objek dengan referensi, fungsi dengan referensi. Lihat referensi MDN untuk info lebih lanjut tentang operator perbandingan).MEMPERBARUI
Dari apa yang saya baca dari komentar, mengurutkan array dan membandingkan dapat memberikan hasil yang akurat:
Misalnya:
Maka kode di atas akan memberi
true
sumber
a1.length==a2.length && a1.every((v,i)=>a2.includes(v))
:var a1 =[1,2,3], a2 = [3,2,1];
(var a1 =[1,3,3], a2 = [1,1,3];
tidak akan berfungsi seperti yang diharapkan)Saya suka menggunakan perpustakaan Underscore untuk proyek pengkodean array / objek berat ... di Underscore dan Lodash apakah Anda membandingkan array atau objek yang hanya terlihat seperti ini:
sumber
_.isEqual([1,2,3], [2,1,3]) => false
isEqual
fungsionalitasnya, Anda selalu dapat menggunakan modul_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Ini menurut saya adalah cara paling sederhana untuk melakukannya menggunakan JSON stringify, dan ini mungkin solusi terbaik dalam beberapa situasi:
Ini mengubah objek
a1
dana2
menjadi string sehingga mereka dapat dibandingkan. Urutan penting dalam kebanyakan kasus, untuk itu dapat mengurutkan objek menggunakan algoritma pengurutan yang ditunjukkan pada salah satu jawaban di atas.Harap dicatat bahwa Anda tidak lagi membandingkan objek tetapi representasi string objek. Mungkin tidak persis seperti yang Anda inginkan.
sumber
Tidak jelas apa yang Anda maksud dengan "identik". Misalnya, apakah array
a
dan dib
bawahnya sama (perhatikan array bersarang)?Berikut adalah fungsi perbandingan array yang dioptimalkan yang membandingkan elemen yang sesuai dari setiap array pada gilirannya menggunakan kesetaraan yang ketat dan tidak melakukan perbandingan berulang elemen array yang merupakan array itu sendiri, yang berarti bahwa untuk contoh di atas,
arraysIdentical(a, b)
akan kembalifalse
. Ini berfungsi dalam kasus umum, yangjoin()
tidak akan digunakan JSON dan solusi:sumber
true
. Jawabannya menjelaskan bahwa itu tidak akan terjadi. Jika Anda perlu membandingkan array bersarang, Anda dapat dengan mudah menambahkan cek rekursif.Cara Praktis
Saya pikir itu salah untuk mengatakan implementasi tertentu adalah "The Right Way ™" jika itu hanya "benar" ("benar") berbeda dengan solusi "salah". Solusi Tomáš adalah peningkatan yang jelas atas perbandingan array berbasis string, tetapi itu tidak berarti itu secara objektif "benar". Apa yang benar ? Apakah ini yang tercepat? Apakah ini yang paling fleksibel? Apakah ini yang termudah untuk dipahami? Apakah ini cara tercepat untuk melakukan debug? Apakah itu menggunakan operasi paling sedikit? Apakah ada efek sampingnya? Tidak ada satu solusi yang dapat memiliki yang terbaik dari semua hal.
Tomáš dapat mengatakan solusinya cepat tetapi saya juga akan mengatakan itu tidak perlu rumit. Itu mencoba untuk menjadi solusi all-in-one yang bekerja untuk semua array, bersarang atau tidak. Bahkan, ia menerima lebih dari sekadar array sebagai input dan masih berusaha memberikan jawaban yang "valid".
Generik menawarkan usabilitas
Jawaban saya akan mendekati masalah secara berbeda. Saya akan mulai dengan
arrayCompare
prosedur generik yang hanya berkaitan dengan melangkah melalui array. Dari sana, kami akan membangun fungsi perbandingan dasar kami sepertiarrayEqual
danarrayDeepEqual
, dllMenurut pendapat saya, jenis kode terbaik bahkan tidak perlu komentar, dan ini tidak terkecuali. Ada begitu sedikit yang terjadi di sini sehingga Anda dapat memahami perilaku prosedur ini dengan hampir tidak ada usaha sama sekali. Tentu, beberapa sintaks ES6 mungkin tampak asing bagi Anda sekarang, tetapi itu hanya karena ES6 relatif baru.
Seperti yang disarankan oleh tipe,
arrayCompare
dibutuhkan fungsi perbandinganf
,, dan dua larik input,xs
danys
. Untuk sebagian besar, yang kita lakukan hanyalah memanggilf (x) (y)
untuk setiap elemen dalam array input. Kami mengembalikan lebih awalfalse
jika pengguna yang ditentukanf
kembalifalse
- berkat&&
evaluasi hubung singkat. Jadi ya, ini berarti komparator dapat menghentikan iterasi lebih awal dan mencegah perulangan melalui sisa array input ketika tidak perlu.Perbandingan yang ketat
Selanjutnya, menggunakan
arrayCompare
fungsi kita, kita dapat dengan mudah membuat fungsi lain yang mungkin kita butuhkan. Kami akan mulai denganarrayEqual
...Sederhana seperti itu.
arrayEqual
dapat didefinisikan denganarrayCompare
dan fungsi pembanding yang membandingkana
denganb
menggunakan===
(untuk kesetaraan yang ketat).Perhatikan bahwa kami juga mendefinisikan
equal
fungsinya sendiri. Ini menyoroti peranarrayCompare
sebagai fungsi tingkat tinggi untuk memanfaatkan pembanding orde pertama kami dalam konteks tipe data lain (Array).Perbandingan longgar
Kita bisa dengan mudah didefinisikan
arrayLooseEqual
menggunakan==
gantinya. Sekarang ketika membandingkan1
(Nomor) ke'1'
(String), hasilnya adalahtrue
...Perbandingan mendalam (rekursif)
Anda mungkin telah memperhatikan bahwa ini hanya perbandingan dangkal. Tentunya solusi Tomáš adalah "The Right Way ™" karena ia melakukan perbandingan mendalam secara implisit, bukan?
Nah
arrayCompare
prosedur kami cukup fleksibel untuk digunakan dengan cara yang membuat tes kesetaraan yang mendalam menjadi mudah ...Sederhana seperti itu. Kami membangun komparator dalam menggunakan fungsi tingkat tinggi lainnya . Kali ini kami membungkus
arrayCompare
menggunakan pembanding khusus yang akan memeriksa apakaha
danb
array. Jika demikian, permohonan kembaliarrayDeepCompare
membandingkana
danb
ke pembanding yang ditentukan pengguna (f
). Ini memungkinkan kita untuk memisahkan perilaku perbandingan mendalam dari bagaimana kita benar-benar membandingkan unsur-unsur individu. Yaitu, seperti contoh di atas menunjukkan, kita bisa membandingkan menggunakanequal
,looseEqual
, atau pembanding lain yang kami buat.Karena
arrayDeepCompare
sudah dikeringkan, kita dapat menerapkannya sebagian seperti yang kita lakukan pada contoh sebelumnya jugaBagi saya, ini sudah merupakan peningkatan yang jelas atas solusi Tomáš karena saya dapat secara eksplisit memilih perbandingan yang dangkal atau dalam untuk array saya, sesuai kebutuhan.
Perbandingan objek (contoh)
Sekarang bagaimana jika Anda memiliki array benda atau sesuatu? Mungkin Anda ingin menganggap array itu sebagai "sama" jika setiap objek memiliki nilai yang sama
id
...Sederhana seperti itu. Di sini saya telah menggunakan objek vanilla JS, tetapi jenis pembanding ini dapat bekerja untuk semua jenis objek; bahkan objek khusus Anda. Solusi Tomáš perlu dikerjakan ulang sepenuhnya untuk mendukung tes kesetaraan semacam ini
Array dalam dengan objek? Bukan masalah. Kami membangun fungsi generik yang sangat fleksibel, sehingga mereka akan bekerja dalam berbagai macam kasus penggunaan.
Perbandingan sewenang-wenang (contoh)
Atau bagaimana jika Anda ingin melakukan semacam perbandingan yang sepenuhnya sewenang-wenang? Mungkin saya ingin tahu apakah masing
x
- masing lebih besar dari masing-masingy
...Kurang itu lebih
Anda dapat melihat kami sebenarnya melakukan lebih banyak dengan lebih sedikit kode. Tidak ada yang rumit tentang itu
arrayCompare
dirinya sendiri dan masing-masing pembanding khusus yang kami buat memiliki implementasi yang sangat sederhana.Dengan mudah, kita dapat mendefinisikan persis bagaimana kita ingin untuk dua array untuk dibandingkan - dangkal, dalam, ketat, longgar, beberapa objek properti, atau beberapa perhitungan sewenang-wenang, atau kombinasi dari ini - semua menggunakan satu prosedur ,
arrayCompare
. Mungkin bahkan bermimpi aRegExp
pembanding! Saya tahu bagaimana anak-anak menyukai regexps itu ...Apakah ini yang tercepat? Nggak. Tapi mungkin juga tidak perlu. Jika kecepatan adalah satu-satunya metrik yang digunakan untuk mengukur kualitas kode kami, banyak kode yang benar-benar hebat akan dibuang - Itulah sebabnya saya menyebut pendekatan ini dengan Cara Praktis . Atau mungkin lebih adil, Cara Praktis. Deskripsi ini cocok untuk jawaban ini karena saya tidak mengatakan jawaban ini hanya praktis dibandingkan dengan beberapa jawaban lainnya; itu benar secara objektif. Kami telah mencapai tingkat kepraktisan yang tinggi dengan kode yang sangat sedikit yang sangat mudah untuk dipikirkan. Tidak ada kode lain yang dapat mengatakan bahwa kami belum mendapatkan deskripsi ini.
Apakah itu menjadikannya solusi "tepat" untuk Anda? Terserah Anda yang memutuskan. Dan tidak ada orang lain yang bisa melakukannya untuk Anda; hanya Anda yang tahu apa kebutuhan Anda. Dalam hampir semua kasus, saya menghargai kode yang mudah, praktis, dan serbaguna daripada jenis yang pintar dan cepat. Apa yang Anda nilai mungkin berbeda, jadi pilihlah yang cocok untuk Anda.
Edit
Jawaban lama saya lebih fokus pada penguraian
arrayEqual
menjadi prosedur kecil. Ini latihan yang menarik, tetapi bukan cara terbaik (paling praktis) untuk mendekati masalah ini. Jika Anda tertarik, Anda dapat melihat riwayat revisi ini.sumber
arrayCompare
? Ya fungsinya sudah dikeringkan, tetapi berbeda darisome
danevery
.arrayCompare
Dibutuhkan pembanding dan dua array untuk membandingkan. Saya memilih nama generik khusus karena kita dapat membandingkan array menggunakan fungsi sembarang. Fungsi ini dikerjakan sehingga dapat dikhususkan untuk membuat fungsi perbandingan array baru (misalnya,arrayEqual
). Bisakah Anda menyarankan nama yang lebih baik? Area apa yang menurut Anda memerlukan komentar atau penjelasan tambahan? Saya senang mendiskusikan ^ _ ^Dalam semangat pertanyaan awal:
Saya telah menjalankan tes kinerja pada beberapa saran yang lebih sederhana yang diusulkan di sini dengan hasil berikut (cepat ke lambat):
sementara (67%) oleh Tim Down
setiap (69%) oleh pengguna2782196
mengurangi (74%) oleh DEI
gabung & toString (78%) oleh Gaizka Allende & vivek
setengah toString (90%) oleh Victor Palomo
stringify (100%) oleh radtek
sumber
Array.from({length: 1000}).map((a,v)=>
$ {v}.padStart(10,2));
Membangun jawaban Tomáš Zato, saya setuju bahwa hanya mengulangi melalui array adalah yang tercepat. Selain itu (seperti yang telah dinyatakan orang lain), fungsi tersebut harus disebut sama dengan / sama, bukan membandingkan. Mengingat hal ini, saya memodifikasi fungsi untuk menangani membandingkan array untuk kesamaan - yaitu mereka memiliki elemen yang sama, tetapi tidak sesuai - untuk penggunaan pribadi, dan saya pikir saya akan melemparkannya ke sini untuk dilihat semua orang.
Fungsi ini mengambil parameter tambahan ketat yang standarnya menjadi true. Parameter ketat ini mendefinisikan jika array harus sepenuhnya sama di kedua konten dan urutan konten tersebut, atau hanya cukup berisi konten yang sama.
Contoh:
Saya juga menulis jsfiddle cepat dengan fungsi dan contoh ini:
http://jsfiddle.net/Roundaround/DLkxX/
sumber
Meskipun ini memiliki banyak jawaban, salah satu yang saya yakin dapat membantu:
Tidak disebutkan dalam pertanyaan bagaimana struktur array akan terlihat seperti, jadi Jika Anda tahu pasti bahwa Anda tidak akan memiliki array bersarang atau objek dalam array Anda (itu terjadi pada saya, itu sebabnya saya datang ke ini jawab) kode di atas akan berfungsi.
Yang terjadi adalah kami menggunakan operator spread (...) untuk menggabungkan kedua array, lalu kami menggunakan Set untuk menghilangkan duplikat apa pun. Setelah Anda memilikinya, Anda dapat membandingkan ukurannya, jika ketiga array memiliki ukuran yang sama, Anda dapat melakukannya.
Jawaban ini juga mengabaikan urutan elemen , seperti yang saya katakan, situasi yang tepat terjadi pada saya, jadi mungkin seseorang dalam situasi yang sama mungkin berakhir di sini (seperti yang saya lakukan).
Edit1.
Menjawab pertanyaan Dmitry Grinko: "Mengapa Anda menggunakan operator spread (...) di sini - ... Perangkat baru? Tidak berfungsi"
Pertimbangkan kode ini:
Anda akan mendapatkannya
Agar dapat bekerja dengan nilai itu, Anda perlu menggunakan beberapa properti Set (lihat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ). Di sisi lain, ketika Anda menggunakan kode ini:
Anda akan mendapatkannya
Itulah bedanya, yang pertama akan memberi saya Set, itu akan bekerja juga karena saya bisa mendapatkan ukuran Set itu, tetapi yang terakhir memberi saya array yang saya butuhkan, apa yang lebih langsung ke resolusi.
sumber
Pada baris yang sama dengan JSON.encode adalah menggunakan join ().
Satu-satunya masalah adalah jika Anda peduli tentang jenis yang diuji perbandingan terakhir. Jika Anda peduli tentang jenis, Anda harus mengulang.
Jika urutannya harus tetap sama, daripada hanya satu lingkaran, tidak ada jenis yang diperlukan.
sumber
.join()
. Mungkin jika Anda menyatakan solusi kedua Anda sebagai yang utama (karena ini adalah solusi yang lebih baik, meskipun ompong terhadap array multidimensi), saya tidak akan menilai Anda seperti itu. Sejauh ini, saya menurunkan semua jawaban yang mengubah array menjadi string. Juga, saya memutakhirkan semua yang menggunakan cara yang benar, jika Anda perlu tahu itu. Ini berarti jawaban @Tim Down dan Bireys satu.checkArrays([1,2,3] , ["1,2",3]) == true
dan sangat tidak mungkin itulah yang Anda inginkan terjadi!join()
seperti ini membuatnya buggy secara halus!Berikut adalah versi naskah:
Beberapa test case untuk moka:
sumber
Jika Anda menggunakan kerangka kerja pengujian seperti Mocha dengan pustaka pernyataan Chai , Anda bisa menggunakan kesetaraan yang mendalam untuk membandingkan array.
Ini harus mengembalikan true hanya jika array memiliki elemen yang sama di indeks yang sesuai.
sumber
Jika hanya dua array angka atau string, ini adalah satu baris cepat
sumber
[11]
. Cukup jelas mengapa ini terjadi dan bagaimana cara memperbaikinya.Dalam kasus saya, array yang dibandingkan hanya berisi angka dan string. Fungsi ini akan menunjukkan kepada Anda jika array mengandung elemen yang sama.
Ayo kita coba!
sumber
are_arrs_equal([1,2], [2,1])
. Juga, lihat diskusi lain di halaman ini untuk alasan pengerasan tidak perlu, rapuh, dan salah.are_arrs_equal([1,2], [2,1])
kembalitrue
seperti yang diharapkan. Mungkin solusi ini tidak ideal, tetapi berhasil untuk saya.are_arrs_match([1,2], ["1,2"])
(pengembaliantrue
). Dan perhatikan bahwathe sort()
panggilan akan mengubah array input - ini mungkin tidak diinginkan.Ini membandingkan 2 array yang tidak disortir:
sumber
Untuk sejumlah angka coba:
Tampilkan cuplikan kode
Catatan: metode ini tidak akan berfungsi ketika array juga mengandung string, mis
a2 = [1, "2,3"]
.sumber
Kita bisa melakukan ini dengan cara fungsional, menggunakan
every
( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )sumber
Kode Anda tidak akan menangani kasus dengan tepat ketika kedua array memiliki elemen yang sama tetapi tidak dalam urutan yang sama.
Lihat kode saya dengan contoh Anda yang membandingkan dua array yang elemen-elemennya adalah angka, Anda dapat memodifikasi atau memperluasnya untuk tipe elemen lainnya (dengan memanfaatkan .join () alih-alih .toString ()).
sumber
Inilah solusi saya:
Bekerja dengan struktur data bersarang, dan jelas mengabaikan metode objek. Jangan pernah berpikir untuk memperluas Object.prototype dengan metode ini, ketika saya mencoba ini sekali, jQuery rusak;)
Untuk sebagian besar array masih lebih cepat daripada sebagian besar solusi serialisasi. Ini mungkin metode perbandingan tercepat untuk array dari catatan objek.
sumber
equal({}, {a:1})
danequal({}, null)
dan kesalahan ini keluar:equal({a:2}, null)
Beginilah cara saya melakukannya.
sumber
Membandingkan 2 array:
fungsi panggilan
sumber
Saya percaya pada polos
JS
dan denganECMAScript 2015
, yang manis dan mudah dimengerti.berharap itu akan membantu seseorang.
sumber
Memperluas ide Tomáš Zato. Tomas's Array.prototype.compare harus benar disebut Array.prototype.compareIdentical.
Itu lewat:
Tetapi gagal pada:
Berikut ini versi yang lebih baik (menurut saya):
http://jsfiddle.net/igos/bcfCY/
sumber
////// ATAU ///////
sumber
Pendekatan lain dengan kode sangat sedikit (menggunakan pengurangan Array dan mencakup Array ):
Jika Anda ingin membandingkan juga kesetaraan pesanan:
The
length
cek memastikan bahwa set elemen dalam satu array bukan hanya bagian dari yang lain.Peredam digunakan untuk berjalan melalui satu array dan mencari setiap item dalam array lain. Jika satu item tidak ditemukan, pengurangan fungsi akan kembali
false
.sumber
Pendekatan sederhana:
sumber
Sudah beberapa jawaban yang bagus. Tetapi saya ingin berbagi ide anter yang telah terbukti andal dalam membandingkan array. Kita dapat membandingkan dua array menggunakan JSON.stringify () . Ini akan membuat string keluar dari array dan dengan demikian membandingkan dua string yang diperoleh dari dua array untuk kesetaraan
sumber
Rekursif & bekerja pada array NESTED :
sumber
Bekerja dengan argumen MULTIPLE dengan array NESTED :
sumber
sumber