Objek `Set`
Artikel ini menerangkan tentang objek Set.
Kami akan menerangkan objek Set dengan contoh-contoh praktikal.
YouTube Video
Objek Set
Set ialah objek terbina dalam yang digunakan untuk mengurus koleksi nilai unik tanpa pendua. Ia membolehkan anda menulis kod untuk menghapus pendua dan semakan kewujudan dengan lebih mudah berbanding dengan array, serta memudahkan pelaksanaan operasi set seperti gabungan (union) dan persilangan (intersection).
Asas: Mewujudkan dan Menggunakan Set
Pertama sekali, mari lihat cara mewujudkan Set, menambah dan membuang elemen, menyemak kewujudan nilai, dan mendapatkan saiznya.
Di bawah ini adalah corak asas yang mewujudkan Set baru dan menunjukkan penggunaan add, has, delete, dan size.
1// Create a Set and demonstrate add, has, delete, and size
2const s = new Set();
3
4s.add(1);
5s.add(2);
6s.add(2); // duplicate, ignored
7
8console.log(s.has(1)); // true
9console.log(s.has(3)); // false
10
11s.delete(2);
12console.log(s.size); // 1
13
14console.log([...s]); // [1]
- Seperti yang ditunjukkan dalam kod ini,
Setsecara automatik membuang nilai primitif yang berulang, dan anda boleh mendapatkan bilangan elemen menggunakansize.
Kaedah iterasi
Set boleh diulang (iterable), jadi anda boleh mengitarinya menggunakan for...of atau forEach. Susunan elemen adalah mengikut turutan kemasukan.
Berikut ialah cara lazim untuk menggunakan for...of dan forEach.
1// Iterate a Set with for...of and forEach
2const s = new Set(['a', 'b', 'c']);
3
4for (const v of s) {
5 console.log('for...of:', v);
6}
7
8s.forEach((value, sameValue, setRef) => {
9 // Note: second arg is same as first for Set API to match Map signature
10 console.log('forEach:', value);
11});- Tandatangan callback untuk
forEachadalahvalue, value, set(untuk keserasian dengan Map), tetapi dalam amalan, anda biasanya hanya memerlukan argumenvalueyang pertama sahaja.
Penukaran antara Array dan Set (berguna untuk membuang pendua)
Di sini kami tunjukkan teknik mudah untuk membuang pendua daripada array, dan cara menukar Set kembali kepada array.
Di bawah ialah contoh membuang pendua daripada array dengan menukar ia kepada Set.
1// Deduplicate an array using Set
2const arr = [1, 2, 2, 3, 3, 3];
3const deduped = [...new Set(arr)];
4console.log(deduped); // [1, 2, 3]
5
6// Convert a Set to an array using Array.from
7const s = new Set([4, 5, 6]);
8const arrFromSet = Array.from(s);
9console.log(arrFromSet); // [4, 5, 6]
- Corak ini ringkas dan pantas, jadi ia sering digunakan untuk membuang pendua dalam array. Ia sangat berkesan untuk nilai-nilai primitif.
Objek dan Pengendalian Rujukan
Objek dalam Set dibandingkan berdasarkan rujukan, jadi objek berbeza walaupun dengan kandungan yang sama akan dianggap sebagai elemen yang berasingan.
Kod berikut menunjukkan apa yang berlaku apabila anda menambah objek ke dalam Set.
1// Objects are compared by reference in a Set
2const obj1 = { x: 1 };
3const obj2 = { x: 1 };
4
5const s = new Set();
6s.add(obj1);
7s.add(obj2);
8
9console.log(s.size); // 2 (different references)
10console.log(s.has(obj1)); // true
11console.log(s.has({ x: 1 })); // false (different object)
- Pengesanan pendua untuk objek adalah berdasarkan identiti rujukan, jadi jika anda ingin menghapuskan pendua berdasarkan kandungan objek sahaja, anda perlu mensiri atau memprosesnya dengan cara lain.
Nilai Khas: Pengendalian NaN dan -0/+0
Set menggunakan peraturan perbandingan Same-value-zero untuk menentukan kesamaan nilai. Kaedah perbandingan ini mempunyai ciri-ciri berikut berkaitan nombor:.
NaNdianggap sama denganNaN.+0(positif) dan-0(negatif) tidak dibezakan dan dianggap sebagai nilai yang sama.
Oleh itu, apabila anda menambah nilai-nilai ini ke dalam Set, kelakuan berikut berlaku:.
1// NaN and zero behavior in Set
2const s = new Set();
3
4s.add(NaN);
5s.add(NaN);
6console.log(s.size); // 1 (NaN considered the same)
7
8s.add(+0);
9s.add(-0);
10console.log(s.size); // still 2 (NaN + 0)
11console.log([...s]); // [NaN, 0] (order may vary but only one zero)
- Dalam perbandingan biasa (
NaN === NaN), ia menghasilkanfalse, tetapi di dalamSet, semua nilaiNaNdianggap sebagai 'nilai yang sama'. - +0 dan -0 boleh dibezakan secara matematik, tetapi dalam
Set, kedua-duanya dianggap hanya sebagai0. - Akibatnya, hanya satu
NaNdan satu0yang kekal dalamSet. - Peraturan perbandingan
Setadalah hampir sama denganObject.is, tetapi tidak seratus peratus sama.Object.is(+0, -0)menghasilkanfalse, tetapi dalamSet, kedua-duanya dianggap sama. Sila ambil perhatian tentang perbezaan ini.
Utiliti Lazim: Operasi Set (Gabungan, Persilangan, Perbezaan)
Operasi set boleh ditulis dengan lebih jelas menggunakan Set. Berikut adalah contoh pelaksanaan yang lazim.
Berikut ialah contoh fungsi untuk union (gabungan), intersection (persilangan), dan difference (perbezaan).
1// Set operations: union, intersection, difference
2function union(a, b) {
3 return new Set([...a, ...b]);
4}
5
6function intersection(a, b) {
7 return new Set([...a].filter(x => b.has(x)));
8}
9
10function difference(a, b) {
11 return new Set([...a].filter(x => !b.has(x)));
12}
13
14// Demo
15const A = new Set([1, 2, 3]);
16const B = new Set([3, 4, 5]);
17
18console.log('union', [...union(A, B)]); // [1,2,3,4,5]
19console.log('intersection', [...intersection(A, B)]); // [3]
20console.log('difference A\\B', [...difference(A, B)]); // [1,2]
- Operasi set boleh ditulis dengan mudah dengan menggunakan penapis (filter) bersama kombinasi
Setdan array. Apabila berurusan dengan set data yang besar, prestasi O(1) bagihasmenjadikan operasi lebih pantas.
Contoh Praktikal: Mencari Perbezaan Array (Mengesan Item Ditambah/Dibuang)
Contoh berikut menunjukkan cara menggunakan Set untuk mencari perbezaan antara dua array (senarai lama dan senarai baharu). Ini membolehkan anda mengenal pasti elemen yang ditambah dan yang dibuang.
1// Find added and removed items between two arrays
2function diffArrays(oldArr, newArr) {
3 const oldSet = new Set(oldArr);
4 const newSet = new Set(newArr);
5
6 const added = [...newSet].filter(x => !oldSet.has(x));
7 const removed = [...oldSet].filter(x => !newSet.has(x));
8
9 return { added, removed };
10}
11
12const oldList = [1, 2, 3];
13const newList = [2, 3, 4, 5];
14
15console.log(diffArrays(oldList, newList));
16// { added: [4,5], removed: [1] }
- Kaedah ini sangat mudah untuk mengesan perbezaan dalam senarai ID, senarai tag, dan situasi yang serupa. Ia paling mudah digunakan untuk nilai-nilai primitif.
Perbezaan Antara WeakSet dan Set (Pengurusan Memori)
WeakSet adalah serupa dengan Set, tetapi ia menggunakan rujukan lemah (weak references), membolehkan itemnya dipadam secara automatik (garbage collected). Berikut menunjukkan penggunaan asas bagi WeakSet.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3let obj = { id: 1 };
4ws.add(obj);
5
6console.log(ws.has(obj)); // true
7
8obj = null; // Now the object is eligible for GC; WeakSet won't prevent collection
WeakSet hanya boleh menyimpan objek dan tidak boleh diiterasi. Di bawah ialah contoh-contoh kekangan WeakSet—ia hanya boleh menyimpan objek, dan tidak boleh diiterasi.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3
4// --- Only objects can be added ---
5try {
6 ws.add(1); // number
7} catch (e) {
8 console.log("Error: WeakSet can only store objects. Adding a number is not allowed.");
9}
10
11try {
12 ws.add("text"); // string
13} catch (e) {
14 console.log("Error: WeakSet can only store objects. Adding a string is not allowed.");
15}
16
17// --- WeakSet is not iterable ---
18try {
19 for (const value of ws) {
20 console.log(value);
21 }
22} catch (e) {
23 console.log("Error: WeakSet is not iterable. You cannot use for...of to loop over its elements.");
24}
25
26// --- Cannot convert to array ---
27try {
28 console.log([...ws]);
29} catch (e) {
30 console.log("Error: WeakSet cannot be converted to an array because it does not support iteration.");
31}
32
33// The object becomes eligible for garbage collection
34let obj = { id: 1 };
35ws.add(obj);
36obj = null;WeakSetberguna untuk menjejak kehadiran objek secara sementara, tetapi anda tidak boleh menyenaraikan elemennya atau mendapatkan saiznya.
Prestasi dan Bilakah Sesuai Digunakan
Apabila menentukan sama ada hendak menggunakan Set, adalah penting untuk memahami ciri-ciri prestasinya dan sifat data anda.
has,add, dandeletebiasanya beroperasi dengan prestasi hampir O(1) secara purata. Oleh itu, dalam situasi di mana anda kerap semak kewujudan nilai atau membuang pendua,Setselalunya lebih berfaedah berbanding array.- Berhati-hati jika anda ingin membuang pendua objek berdasarkan kandungan (nilai) mereka. Oleh kerana
Setmembandingkan berdasarkan rujukan, cara praktikal adalah dengan menggunakan ID atau kunci lain, atau menjadikan objek sebagai nilai primitif sebelum menggunakan Set jika perbandingan berdasarkan nilai diperlukan. Setsangat berguna untuk meningkatkan kebolehbacaan kod bagi koleksi yang kecil hingga sederhana. Sebaliknya, jika anda mengendalikan bilangan elemen yang sangat banyak atau kerap menukar antara array dan Set, disarankan supaya benar-benar melakukan penanda aras dan ujian.
Kesilapan Lazim
Set sangat mudah digunakan, tetapi jika anda tidak menyedari spesifikasinya, anda mungkin keliru dengan tingkah laku yang tidak dijangka. Berikut ialah beberapa perkara lazim yang perlu diberi perhatian:.
- Objek dibandingkan berdasarkan rujukan, jadi walaupun kandungan mereka sama, objek yang berbeza tidak dianggap sebagai pendua.
Setmengekalkan susunan kemasukan, tetapi anda tidak boleh mengakses elemen menggunakan indeks seperti array. Jika anda mahu mengakses berdasarkan indeks, tukarkanSetkepada array dahulu.WeakSettidak boleh disenaraikan, dan hanya boleh menyimpan objek. Perhatikan bahawa penggunaannya adalah terhad.NaNdianggap nilai yang sama, dan+0serta-0tidak dibezakan. Ini disebabkan oleh peraturan perbandingan Same-value-zero.
Ringkasan
Set ialah struktur data yang mudah digunakan untuk mengendalikan koleksi nilai unik secara intuitif. Anda boleh menggunakannya untuk membuang pendua daripada array, melakukan semakan kewujudan dengan pantas, atau melaksanakan operasi set seperti gabungan dan persilangan dengan kod yang ringkas dan mudah dibaca.
Sebaliknya, kerana objek dibandingkan berdasarkan rujukan, langkah tambahan diperlukan jika anda ingin menentukan persamaan berdasarkan kandungannya.
Dengan memahami ciri-ciri ini dan menggunakannya dengan betul, Set menjadi pilihan yang berkuasa untuk meningkatkan kebolehbacaan dan penyenggaraan kod.
Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.