`Set`-objekt
Denne artikel forklarer Set-objektet.
Vi vil forklare Set-objektet med praktiske eksempler.
YouTube Video
Set-objekt
Set er et indbygget objekt, der bruges til at håndtere samlinger af unikke, ikke-duplicate værdier. Det gør det nemmere at skrive kode til at fjerne dubletter og kontrollere eksistens end med arrays, og gør mængdeoperationer som union og snit lettere at implementere.
Grundlæggende: Oprettelse og brug af Sets
Lad os først se på, hvordan man opretter et Set, tilføjer og fjerner elementer, tjekker for eksistens og får størrelsen.
Nedenfor er et grundlæggende eksempel, der opretter et nyt Set og demonstrerer add, has, delete og 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]
- Som vist i denne kode, fjerner
Setautomatisk dublerede primitive værdier, og du kan få antallet af elementer ved hjælp afsize.
Iterationmetoder
Set kan itereres over, så du kan gennemløbe det med for...of eller forEach. Rækkefølgen er indsættelsesrækkefølgen.
Her er typiske måder at bruge for...of og forEach på.
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});- Callback-signaturen for
forEachervalue, value, set(for kompatibilitet med Map), men i praksis har du normalt kun brug for det førstevalue-argument.
Konvertering mellem arrays og Sets (nyttigt til at fjerne dubletter)
Her viser vi en simpel teknik til at fjerne dubletter fra et array og hvordan man konverterer et Set tilbage til et array.
Nedenfor er et eksempel på at fjerne dubletter fra et array ved at sende det igennem et 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]
- Dette mønster er kort og hurtigt, så det bruges ofte til at fjerne dubletter fra arrays. Det er især effektivt for primitive værdier.
Objekter og referencestyring
Objekter i et Set sammenlignes efter reference, så forskellige instanser med samme indhold behandles som separate elementer.
Den følgende kode demonstrerer, hvad der sker, når du tilføjer objekter til et 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)
- Dubletkontrol for objekter er baseret på referencelighed, så hvis du vil fjerne dubletter på baggrund af objektindhold alene, skal du serialisere eller på anden måde behandle dem.
Specielle værdier: håndtering af NaN og -0/+0
Set bruger Same-value-zero-sammenligningsreglen til at bestemme værdi-lighed. Denne sammenligningsmetode har følgende karakteristika for tal:.
NaNanses for at være lig medNaN.- Positiv
+0og negativ-0skelnes ikke og behandles som samme værdi.
Derfor, når du tilføjer disse værdier til et Set, sker følgende:.
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)
- Ved normal sammenligning (
NaN === NaN), returnerer detfalse, men i etSetbetragtes alleNaN-værdier som 'samme værdi'. - +0 og -0 kan matematisk skelnes, men i et
Setbehandles de blot som0. - Som resultat forbliver kun én
NaNog én0iSet. - Sammenligningsreglen for
SetlignerObject.is, men er ikke helt den samme.Object.is(+0, -0)returnererfalse, men i etSetbetragtes de som identiske. Vær opmærksom på denne forskel.
Almindelige funktioner: Mængdeoperationer (union, snit, differens)
Mængdeoperationer kan skrives mere klart med Set. Nedenfor er almindelige implementeringseksempler.
Her er eksempler på funktioner for union, intersection og difference.
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]
- Mængdeoperationer kan nemt skrives ved at bruge filtre med en kombination af
Setog arrays. Når du arbejder med store datasæt, gør O(1)-ydeevnen afhasoperationer hurtigere.
Praktisk eksempel: Find forskelle mellem arrays (opdage tilføjede/fjernede elementer)
Følgende eksempel viser, hvordan man bruger et Set til at finde forskellen mellem to arrays (en gammel og en ny liste). Dette gør det muligt at identificere, hvilke elementer der blev tilføjet, og hvilke der blev fjernet.
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] }
- Denne metode er meget bekvem til at opdage forskelle i ID-lister, tag-lister og lignende situationer. Det er nemmest at bruge med primitive værdier.
Forskelle mellem WeakSet og Set (hukommelsesstyring)
WeakSet ligner Set, men bruger svage referencer, hvilket tillader dets elementer at blive affaldsindsamlet. Det følgende demonstrerer grundlæggende anvendelser af 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 kan kun indeholde objekter og kan ikke itereres over. Nedenfor er eksempler på begrænsningerne ved WeakSet—det kan kun indeholde objekter og kan ikke itereres.
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;WeakSeter nyttigt til midlertidigt at holde styr på tilstedeværelsen af objekter, men du kan ikke enumerere dets elementer eller få dets størrelse.
Ydeevne og valg af anvendelse
Når du beslutter, om du skal bruge et Set, er det vigtigt at forstå dets ydeevne og datatyperne.
has,addogdeletefungerer som regel med næsten O(1) ydeevne i gennemsnit. Derfor erSetofte mere fordelagtigt end arrays i scenarier, hvor du ofte tjekker for eksistens eller fjerner dubletter.- Vær opmærksom, hvis du vil fjerne dubletter blandt objekter baseret på deres indhold (værdier). Da
Setsammenligner efter reference, er en praktisk metode at bruge ID'er eller andre nøgler, eller serialisere objekter til primitive værdier før brug af Sets, når sammenligning efter værdi er nødvendig. Seter især nyttigt for at forbedre kode-læseligheden for små til mellemstore samlinger. Omvendt, hvis du arbejder med et meget stort antal elementer eller ofte konverterer mellem arrays og Sets, anbefales det at benchmarke og teste.
Almindelige faldgruber
Set er praktisk, men hvis du ikke er opmærksom på dets specifikationer, kan du blive overrasket over uventet adfærd. Her er nogle typiske ting, du skal være opmærksom på:.
- Objekter sammenlignes efter reference, så selv om deres indhold er det samme, anses forskellige objekter ikke som dubletter.
Setopretholder indsættelsesrækkefølgen, men du kan ikke tilgå elementer via index som i arrays. Hvis du vil bruge indeksbaseret adgang, skal du først konvertereSettil et array.WeakSetkan ikke enumereres og kan kun indeholde objekter. Bemærk, at anvendelsesmulighederne er begrænsede.NaNbehandles som samme værdi, og+0og-0skelnes ikke. Dette skyldes Same-value-zero-sammenligningsreglen.
Sammendrag
Set er en praktisk datastruktur, der gør det nemt at håndtere samlinger af unikke værdier. Du kan bruge det til at fjerne dubletter fra arrays, lave hurtige eksistenstjek eller implementere mængdeoperationer som union og snit med enkel og læsbar kode.
Omvendt kræves ekstra tiltag, hvis du vil sammenligne objekter baseret på deres indhold, da objekter sammenlignes efter reference.
Ved at forstå disse karakteristika og bruge dem korrekt, bliver Set et kraftfuldt valg til at forbedre kodens læsbarhed og vedligeholdelse.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.