Objektet `Set`
Denna artikel förklarar objektet Set.
Vi förklarar objektet Set med praktiska exempel.
YouTube Video
Objektet Set
Set är ett inbyggt objekt som används för att hantera samlingar av unika, icke-duplicerade värden. Det låter dig skriva borttagning av dubbletter och existenskontroller enklare än med arrayer, och gör mängdoperationer som union och snitt lättare att implementera.
Grunder: Skapa och använda Set
Först tittar vi på hur man skapar ett Set, lägger till och tar bort element, kontrollerar om ett värde finns och hämtar dess storlek.
Nedan är ett grundläggande exempel som skapar ett nytt Set och demonstrerar add, has, delete och 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 visas i denna kod tar
Setautomatiskt bort dubbletter av primitiva värden, och du kan få antalet element med hjälp avsize.
Itereringsmetoder
Set är itererbar, så du kan loopa över den med hjälp av for...of eller forEach. Ordningen är insättningsordningen.
Här är typiska sätt att använda for...of och 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});- Signaturen för callback-funktionen i
forEachärvalue, value, set(för kompatibilitet med Map), men i praktiken använder du oftast bara det första argumentetvalue.
Konvertering mellan arrayer och Set (användbart för att ta bort dubbletter)
Här visar vi en enkel teknik för att ta bort dubbletter från en array och hur du konverterar ett Set tillbaka till en array.
Nedan är ett exempel på att ta bort dubbletter från en array genom att skicka den genom ett 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]
- Detta mönster är kort och snabbt, så det används ofta för att ta bort dubbletter i arrayer. Det är särskilt effektivt för primitiva värden.
Objekt och referenshantering
Objekt i ett Set jämförs med referenser, så olika instanser med samma innehåll behandlas som separata element.
Följande kod visar vad som händer när du lägger till objekt i ett 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)
- Upptäckt av dubbletter för objekt baseras på referensidentitet, så om du vill ta bort dubbletter baserat på objektinnehåll måste du serialisera eller bearbeta dem på annat sätt.
Speciella värden: Hantering av NaN och -0/+0
Set använder jämförelseregeln Same-value-zero för att avgöra värdeekvivalens. Denna jämförelsemetod har följande egenskaper för siffror:.
NaNanses vara lika medNaN.- Positivt
+0och negativt-0särskiljs inte utan behandlas som samma värde.
Därför, när du lägger till dessa värden i ett Set, uppstår följande beteende:.
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)
- Vid normal jämförelse (
NaN === NaN) returnerasfalse, men i ettSetbetraktas allaNaN-värden som 'samma värde'. - +0 och -0 kan särskiljas matematiskt, men i ett
Setbehandlas de helt enkelt som0. - Därför finns bara en
NaNoch en0kvar iSet. - Jämförelseregeln för
SetliknarObject.is, men är inte exakt densamma.Object.is(+0, -0)returnerarfalse, men i ettSeträknas de som identiska. Observera denna skillnad.
Vanligt användningsområde: Mängdoperationer (union, snitt, differens)
Mängdoperationer kan skrivas tydligare med hjälp av Set. Nedan är vanliga implementations-exempel.
Här är exempel på funktioner för union, intersection och 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ängdoperationer kan skrivas enkelt genom att använda filter i kombination med
Setoch arrayer. Vid hantering av stora datamängder ger O(1) prestanda förhassnabbare operationer.
Praktiskt exempel: Hitta skillnader mellan arrayer (upptäckta tillagda/borttagna poster)
Följande exempel visar hur du kan använda ett Set för att hitta skillnaden mellan två arrayer (en gammal och en ny lista). Detta gör det möjligt att identifiera vilka element som har lagts till och vilka som har tagits bort.
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] }
- Denna metod är mycket praktisk för att upptäcka skillnader i ID-listor, tagglistor och liknande situationer. Det är enklast att använda med primitiva värden.
Skillnader mellan WeakSet och Set (minneshantering)
WeakSet liknar Set, men den använder svaga referenser vilket gör att dess objekt kan garbage-samlas (tas bort automatiskt). Följande visar grundläggande användning 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 endast innehålla objekt och kan inte itereras över. Nedan är exempel på begränsningarna för WeakSet—det innehåller bara objekt och kan inte itereras över.
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;WeakSetär användbart för att tillfälligt hålla koll på förekomsten av objekt, men du kan inte räkna upp dess element eller ta reda på dess storlek.
Prestanda och hur man väljer när man ska använda
När du bestämmer dig för om du ska använda ett Set är det viktigt att förstå dess prestanda och datans natur.
has,addochdeletefungerar i genomsnitt med nästan O(1)-prestanda. Därför ärSetofta mer fördelaktigt än arrayer vid frekventa existenskontroller eller borttagning av dubbletter.- Var försiktig om du vill ta bort dubbletter av objekt baserat på deras innehåll (värden). Eftersom
Setjämför med referenser är ett praktiskt sätt att använda ID:n eller andra nycklar, eller att serialisera objekt till primitiva värden innan du använder Sets om du behöver jämföra baserat på värde. Setär särskilt användbart för att förbättra kodläsbarheten för små till medelstora samlingar. Å andra sidan, om du hanterar ett mycket stort antal element eller ofta konverterar mellan arrayer och Set, rekommenderas det att faktiskt mäta prestanda och testa.
Vanliga fallgropar
Set är bekvämt, men om du inte känner till dess specifikationer kan du bli förvirrad av oväntat beteende. Här är några typiska saker att vara uppmärksam på:.
- Objekt jämförs med referenser, så även om innehållet är detsamma, räknas olika objekt inte som dubbletter.
Setbehåller insättningsordningen, men du kan inte komma åt element med index som med arrayer. Om du vill använda indexbaserad åtkomst, konvertera förstSettill en array.WeakSetkan inte enumreras och kan bara lagra objekt. Observera att dess användningsområden är begränsade.NaNbehandlas som samma värde, och+0och-0särskiljs inte. Detta beror på jämförelseregeln Same-value-zero.
Sammanfattning
Set är en bekväm datastruktur som låter dig hantera samlingar av unika värden på ett intuitivt sätt. Du kan använda det för att ta bort dubbletter från arrayer, göra snabba existenskontroller eller implementera mängdoperationer som union och snitt med enkel och läsbar kod.
Å andra sidan, eftersom objekt jämförs med referenser, krävs extra åtgärder om du vill avgöra likhet baserat på deras innehåll.
Genom att förstå dessa egenskaper och använda dem rätt blir Set ett kraftfullt val för att förbättra kodens läsbarhet och underhållbarhet.
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.