`Set`-objekt
Denne artikkelen forklarer Set-objektet.
Vi vil forklare Set-objektet med praktiske eksempler.
YouTube Video
Set-objekt
Set er et innebygd objekt brukt til å håndtere samlinger av unike, ikke-dupliserte verdier. Det lar deg utføre fjerning av duplikater og eksistenssjekk enklere enn med arrayer, og gjør det lettere å implementere mengdeoperasjoner som union og snitt.
Grunnleggende: Lage og bruke Set
Først skal vi se på hvordan man lager et Set, legger til og fjerner elementer, sjekker for eksistens, og finner størrelsen.
Nedenfor er et grunnleggende mønster som lager et nytt Set og demonstrerer bruk av 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 koden, fjerner
Setautomatisk dupliserte primitive verdier, og du kan få antall elementer ved å brukesize.
Iterasjonsmetoder
Set er itererbar, så du kan gå gjennom den med for...of eller forEach. Rekkefølgen er den samme som innsettingsrekkefølgen.
Her er typiske måter å bruke 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 trenger du vanligvis kun det førstevalue-argumentet.
Konvertering mellom arrayer og Set (nyttig for å fjerne duplikater)
Her viser vi en enkel teknikk for å fjerne duplikater fra en array og hvordan du konverterer et Set tilbake til en array.
Nedenfor er et eksempel på å fjerne duplikater fra en array ved å føre den gjennom 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ønsteret er kort og raskt, så det brukes ofte for å fjerne duplikater fra arrayer. Det er spesielt effektivt for primitive verdier.
Objekter og referansehåndtering
Objekter i et Set sammenlignes på referanse, så forskjellige instanser med samme innhold behandles som separate elementer.
Koden nedenfor demonstrerer hva som skjer når du legger til objekter i 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)
- Duplikatdeteksjon for objekter er basert på referanseidentitet, så hvis du vil fjerne duplikater basert på objektinnhold alene, må du serialisere eller på annen måte behandle dem.
Spesielle verdier: Håndtering av NaN og -0/+0
Set bruker Same-value-zero-sammenligningsregelen for å bestemme likhet mellom verdier. Denne sammenligningsmetoden har følgende egenskaper med hensyn til tall:.
NaNregnes som likNaN.- Positiv
+0og negativ-0skilles ikke, og behandles som samme verdi.
Derfor, når du legger til disse verdiene i et Set, oppstår følgende oppførsel:.
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 vanlig sammenligning (
NaN === NaN) får dufalse, men i etSetregnes alleNaN-verdier som 'samme verdi'. - +0 og -0 kan skilles matematisk, men i et
Setblir de bare behandlet som0. - Som resultat forblir kun én
NaNog én0iSet. - Sammenligningsregelen for
Setligner påObject.is, men er ikke helt den samme.Object.is(+0, -0)returnererfalse, men i etSetanses de som identiske. Vennligst merk deg denne forskjellen.
Vanlige verktøy: Mengdeoperasjoner (union, snitt, differanse)
Mengdeoperasjoner kan skrives tydeligere ved bruk av Set. Nedenfor er vanlige implementeringseksempler.
Her er eksempler på funksjoner 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]
- Mengdeoperasjoner kan enkelt skrives ved å bruke filterfunksjoner med en kombinasjon av
Setog arrayer. Når man jobber med store datasett, gjør O(1)-ytelsen tilhasoperasjoner raskere.
Praktisk eksempel: Finne forskjeller mellom arrayer (oppdage tilføyde/fjernede elementer)
Eksempelet nedenfor viser hvordan man bruker et Set for å finne forskjellen mellom to arrayer (en gammel liste og en ny liste). Dette lar deg identifisere hvilke elementer som ble lagt til og hvilke som ble 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 metoden er svært praktisk for å oppdage forskjeller i ID-lister, tag-lister og lignende situasjoner. Det er enklest å bruke med primitive verdier.
Forskjeller mellom WeakSet og Set (minnehåndtering)
WeakSet ligner på Set, men bruker svake referanser, noe som gjør at elementene kan samles inn av søppeloppsamleren. Nedenfor demonstreres grunnleggende bruk av 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 inneholde objekter og kan ikke itereres over. Nedenfor er eksempler på begrensningene til WeakSet – det kan bare inneholde objekter, og kan ikke itereres over.
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 nyttig for midlertidig sporing av objekters tilstedeværelse, men du kan hverken enumerere elementene eller finne størrelsen.
Ytelse og valg av bruk
Når du vurderer om du skal bruke et Set, er det viktig å forstå ytelsesegenskapene og typen data du har.
has,addogdeletekjører vanligvis i nær O(1) ytelse i gjennomsnitt. Derfor erSetofte mer fordelaktig enn arrayer i scenarioer hvor du ofte sjekker for eksistens eller fjerner duplikater.- Vær obs hvis du ønsker å fjerne duplikater på grunnlag av objektenes innhold (verdier). Siden
Setsammenligner etter referanse, er en praktisk løsning å bruke ID-er eller andre nøkler, eller serialisere objektene til primitive verdier før du bruker Set, når verdibasert sammenligning er nødvendig. Seter spesielt nyttig for å forbedre lesbarheten av kode for små til middels store samlinger. På den annen side, hvis du jobber med svært mange elementer eller ofte konverterer mellom arrayer og Set, anbefales det å benchmarke og teste faktisk.
Vanlige fallgruver
Set er praktisk, men hvis du ikke kjenner til spesifikasjonene, kan du bli overrasket over uventet oppførsel. Her er noen typiske ting du bør passe på:.
- Objekter blir sammenlignet etter referanse, så selv om innholdet er det samme regnes ulike objekter ikke som duplikater.
Setbevarer innsettingsrekkefølgen, men du kan ikke få tilgang til elementer med indeks slik du kan med arrayer. Hvis du vil bruke indekser-basert tilgang, konverter førstSettil en array.WeakSetkan ikke enumreres og kan kun lagre objekter. Merk at bruksområdene er begrenset.NaNbehandles som samme verdi, og+0og-0skilles ikke. Dette skyldes Same-value-zero-sammenligningsregelen.
Sammendrag
Set er en praktisk datastruktur som lar deg håndtere samlinger av unike verdier på en intuitiv måte. Du kan bruke det for å fjerne duplikater fra arrayer, gjøre raske eksistenssjekker eller implementere mengdeoperasjoner som union og snitt med enkel og lesbar kode.
På den annen side, siden objekter sammenlignes på referanse, er ekstra tiltak nødvendige hvis du vil sammenligne basert på innholdet deres.
Ved å forstå disse egenskapene og bruke dem riktig, blir Set et kraftig valg for å bedre kode-lesbarhet og vedlikeholdbarhet.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.