Apa kode sederhana, bebas perpustakaan untuk mengimplementasikan persimpangan array di javascript? saya ingin menulis
intersection([1,2,3], [2,3,4,5])
dan dapatkan
[2, 3]
Apa kode sederhana, bebas perpustakaan untuk mengimplementasikan persimpangan array di javascript? saya ingin menulis
intersection([1,2,3], [2,3,4,5])
dan dapatkan
[2, 3]
break
untukSimple js loops
meningkatkan ops / detik hingga ~ 10MJawaban:
Gunakan kombinasi dari
Array.prototype.filter
danArray.prototype.indexOf
:Atau seperti yang disarankan vrugtehagel di komentar, Anda dapat menggunakan yang lebih baru
Array.prototype.includes
untuk kode yang lebih sederhana:Untuk browser lama:
sumber
intersection([1,2,1,1,3], [1])
kembali[1, 1, 1]
. Bukankah seharusnya kembali[1]
?array2.indexOf(n) != -1
satu juga dapat menulisarray2.includes(n)
untuk kode lebih sederhana.Merusak tampaknya paling sederhana, terutama jika kita dapat berasumsi bahwa input diurutkan:
Non-destruktif harus menjadi rambut yang lebih rumit, karena kita harus melacak indeks:
sumber
intersect_safe
:length
adalah properti di Array, bukan metode. Ada variabel yang tidak dihapusi
dalamresult.push(a[i]);
. Akhirnya, ini sama sekali tidak berfungsi dalam kasus umum: dua objek di mana tidak ada yang lebih besar dari yang lain menurut>
operator belum tentu sama.intersect_safe( [ {} ], [ {} ] )
, misalnya, akan memberikan (setelah kesalahan yang disebutkan sebelumnya diperbaiki) array dengan satu elemen, yang jelas salah..slice(0)
untuk membuat klon dari arrayintersect_safe
, bukan melacak indeks.Jika lingkungan Anda mendukung ECMAScript 6 Set , satu cara sederhana dan seharusnya efisien (lihat tautan spesifikasi):
Lebih pendek, tetapi kurang dapat dibaca (juga tanpa membuat persimpangan tambahan
Set
):Menghindari yang baru
Set
darib
setiap waktu:Perhatikan bahwa saat menggunakan set Anda hanya akan mendapatkan nilai yang berbeda, jadi
new Set[1,2,3,3].size
dievaluasi untuk3
.sumber
[...setA]
sintaksis ini ? Beberapa jenis operasi javascript khusus?x => new Set(b).has(x)
fungsi panah itu berubahb
menjadi set setiap kali dieksekusi? Anda mungkin harus menyimpan set itu dalam sebuah variabel.Menggunakan Underscore.js atau lodash.js
sumber
Kontribusi saya dalam istilah ES6. Secara umum ia menemukan persimpangan array dengan jumlah array yang tidak terbatas yang disediakan sebagai argumen.
sumber
[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7],[4,6]]
dan kemudian berlaku.reduce()
.[0,1,2,3,4,5,6,7,8,9].filter( e => [0,2,4,6,8].includes(e)
Operasi pertama dilakukan dan hasilnya menjadi barup
danc
menjadi[4,5,6,7]
di belokan berikutnya dan berlanjut seterusnya hingga tidak ada lagic
yang tersisa.prototype
tidak perlu.Saya merekomendasikan solusi ringkas di atas yang mengungguli implementasi lainnya pada input besar. Jika kinerja pada input kecil penting, periksa alternatif di bawah ini.
Alternatif dan perbandingan kinerja:
Lihat cuplikan berikut untuk implementasi alternatif dan periksa https://jsperf.com/array-intersection-comparison untuk perbandingan kinerja.
Tampilkan cuplikan kode
Hasil di Firefox 53:
Ops / dtk pada array besar (10.000 elemen):
Ops / dtk pada array kecil (100 elemen):
sumber
intersect([1,2,2,3], [2,3,4,5])
kembali[2, 2, 3]
.a.filter(b.includes)
. Ini harus berjalan jauh lebih cepat (sama seperti peningkatan fungsi Anda).Bagaimana kalau hanya menggunakan array asosiatif?
edit:
sumber
Object.prototype
.d[b[i]] = true;
bukand[b[j]] = true;
(i
tidakj
). Tetapi pengeditan membutuhkan 6 karakter.Sesuatu seperti ini, Tidak diuji dengan baik.
PS: Algoritma hanya ditujukan untuk Bilangan dan String Normal, persimpangan array objek arbiter mungkin tidak berfungsi.
sumber
Kinerja implementasi @ atk untuk array primitif yang diurutkan dapat ditingkatkan dengan menggunakan .pop daripada .shift.
Saya membuat tolok ukur menggunakan jsPerf: http://bit.ly/P9FrZK . Sekitar tiga kali lebih cepat untuk menggunakan .pop.
sumber
a[aLast] > b[bLast]
dengana[aLast].localeCompare(b[bLast]) > 0
(dan sama dengan dielse if
bawah) maka ini akan berfungsi pada string..pop
O (1) dan.shift()
O (n)Menggunakan jQuery :
sumber
c = $(b).filter(a);
, tetapi saya tidak akan merekomendasikan bergantung pada jQuery untuk manipulasi array semacam ini karena dokumentasi hanya menyebutkan bahwa itu berfungsi untuk elemen.Untuk array yang hanya berisi string atau angka, Anda dapat melakukan sesuatu dengan menyortir, seperti beberapa jawaban lainnya. Untuk kasus umum array benda sewenang-wenang, saya tidak berpikir Anda bisa menghindari melakukannya jauh-jauh. Berikut ini akan memberi Anda persimpangan sejumlah array yang disediakan sebagai parameter untuk
arrayIntersection
:sumber
firstArr
ataufirstArray
tidak dan tidak memperbarui semua referensi. Tetap.Cukup singkat menggunakan ES2015 dan Perangkat. Menerima nilai seperti Array seperti String dan menghapus duplikat.
sumber
Anda bisa menggunakan
Set
sebagaithisArg
dariArray#filter
dan mengambilSet#has
sebagai callback.sumber
Tweak kecil ke yang terkecil di sini (solusi filter / indexOf ), yaitu membuat indeks nilai di salah satu array menggunakan objek JavaScript, akan menguranginya dari O (N * M) menjadi "mungkin" waktu linear. sumber1 sumber2
Ini bukan solusi yang paling sederhana (ini lebih dari kode filter + indexOf ), juga bukan yang paling cepat (mungkin lebih lambat oleh faktor konstan daripada intersect_safe () ), tetapi sepertinya keseimbangan yang cukup bagus. Itu di sisi yang sangat sederhana, sambil memberikan kinerja yang baik, dan itu tidak memerlukan input pra-disortir.
sumber
Pendekatan lain yang diindeks dapat memproses sejumlah array sekaligus:
Ini hanya berfungsi untuk nilai yang dapat dievaluasi sebagai string dan Anda harus meneruskannya sebagai array seperti:
... tetapi secara transparan menerima objek sebagai parameter atau sebagai salah satu elemen yang akan berpotongan (selalu mengembalikan array nilai-nilai umum). Contoh:
EDIT: Saya hanya memperhatikan bahwa ini, sedikit banyak, bermasalah.
Yaitu: Saya mengkodekannya berpikir bahwa input array tidak dapat dengan sendirinya mengandung pengulangan (seperti contoh yang diberikan tidak).
Tetapi jika array input kebetulan mengandung pengulangan, itu akan menghasilkan hasil yang salah. Contoh (menggunakan implementasi di bawah):
Untungnya ini mudah diperbaiki dengan hanya menambahkan pengindeksan tingkat kedua. Itu adalah:
Perubahan:
oleh:
...dan:
oleh:
Contoh lengkap:
sumber
var v =
baris tambahkanif (typeof v == 'function') continue;
dan itu akan melewatkan fungsi menambahkan ke hasil. Terima kasih!if (typeof v == 'function')
, maka kita dapat menggunakan stringifikasi (v.toString()
) sebagai kunci untuk indeks. Tapi, kita perlu melakukan sesuatu untuk mempertahankannya tetap utuh. Cara termudah untuk melakukannya adalah hanya menetapkan fungsi asli sebagai nilai alih-alih nilai boolean yang sebenarnya, tetapi, dalam hal itu, deindexaton terbaru juga harus diubah untuk mendeteksi kondisi ini dan mengembalikan nilai yang tepat (fungsi).Anda dapat menggunakan (untuk semua browser kecuali IE):
atau untuk IE:
sumber
sumber
Dengan beberapa batasan pada data Anda, Anda dapat melakukannya dalam waktu linier !
Untuk bilangan bulat positif : gunakan array yang memetakan nilai ke boolean "terlihat / tidak terlihat".
Ada teknik serupa untuk objek : ambil kunci dummy, setel ke "true" untuk setiap elemen dalam array1, lalu cari kunci ini di elemen array2. Bersihkan saat Anda selesai.
Tentu saja Anda perlu memastikan bahwa kunci tersebut tidak muncul sebelumnya, jika tidak, Anda akan menghancurkan data Anda ...
sumber
Saya akan berkontribusi dengan apa yang paling berhasil bagi saya:
sumber
"indexOf" untuk IE 9.0, chrome, firefox, opera,
sumber
sumber
Pendekatan fungsional dengan ES2015
Pendekatan fungsional harus mempertimbangkan hanya menggunakan fungsi murni tanpa efek samping, yang masing-masing hanya berkaitan dengan satu pekerjaan.
Pembatasan ini meningkatkan kemampuan menyusun dan penggunaan kembali fungsi yang terlibat.
Harap dicatat bahwa
Set
jenis asli digunakan, yang memiliki kinerja pencarian yang menguntungkan.Hindari duplikat
Jelas item berulang kali terjadi dari yang pertama
Array
dipertahankan, sedangkan yang keduaArray
diduplikasi. Ini mungkin atau mungkin bukan perilaku yang diinginkan. Jika Anda membutuhkan hasil yang unik, hanya berlakudedupe
untuk argumen pertama:Hitung persimpangan dari sejumlah
Array
sJika Anda ingin menghitung persimpangan jumlah sewenang-wenang
Array
hanya menulisintersect
denganfoldl
. Berikut ini adalah fungsi kenyamanan:sumber
(expr ? true : false)
redundan. Gunakan hanyaexpr
jika boolean yang sebenarnya tidak diperlukan, cukup jujur / palsu.Untuk kesederhanaan:
Manfaat:
Kekurangan:
Anda tidak ingin menggunakan ini untuk mesin 3D atau kerja kernel, tetapi jika Anda memiliki masalah menjalankan ini di aplikasi berbasis acara, desain Anda memiliki masalah yang lebih besar.
sumber
.reduce
untuk membangun peta, dan.filter
untuk menemukan persimpangan.delete
dalam.filter
memungkinkan kita untuk memperlakukan array kedua seolah-olah itu satu set yang unik.Saya menemukan pendekatan ini cukup mudah untuk dipikirkan. Ia melakukan dalam waktu yang konstan.
sumber
Ini mungkin yang paling sederhana, selain list1.filter (n => list2.includes (n))
sumber
Jika Anda perlu mengatasinya memotong beberapa array:
sumber
Cara sederhana ala ES6.
Contoh:
sumber
Saya telah menulis fungsi interseksi yang bahkan dapat mendeteksi persimpangan array objek berdasarkan properti tertentu dari objek-objek tersebut.
Contohnya,
dan kami ingin persimpangan berdasarkan
id
properti, maka outputnya harus:Dengan demikian, fungsi untuk hal yang sama (catatan: kode ES6) adalah:
dan Anda dapat memanggil fungsinya sebagai:
Perhatikan juga: fungsi ini menemukan persimpangan mengingat array pertama adalah array primer dan dengan demikian hasil persimpangan akan menjadi array utama.
sumber
Pikir ini akan lebih cepat dengan O (array1 + array2) waktu dengan asumsi map.has () adalah ~ O (1). Tolong koreksi saya jika salah.
sumber
Berikut ini adalah implementasi underscore.js :
Sumber: http://underscorejs.org/docs/underscore.html#section-62
sumber