HashSet og entydighed
Hold styr på forskellige værdier.
HashSet og entydighed er en gratis C# Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C# Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C# Academy-kurset indeholder 4 lektioner i alt.
Hvad er en HashSet?
HashSet<T> gemmer en samling af unikke værdier uden dubletter. Hvis du tilføjer en værdi, der allerede findes, sker der ganske enkelt ingenting.
Ligesom en ordbog er den baseret på en hash-tabel, så medlemskabstjek tager i gennemsnit O(1). Den bevarer ikke indsættelsesrækkefølgen.
using System.Collections.Generic;
var seen = new HashSet<int>();
seen.Add(1);
seen.Add(1); // ignored, still one elementAdd returnerer en bool
Add returnerer true, hvis værdien var ny, og false, hvis den allerede fandtes.
Returværdien er nyttig til at opdage dubletter i ét trin uden et separat Contains-tjek.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var set = new HashSet<string>();
Console.WriteLine(set.Add("a")); // True
Console.WriteLine(set.Add("a")); // False
}
}Hurtige medlemskabstjek
Contains på en HashSet tager i gennemsnit O(1), sammenlignet med O(n) på en List.
Når du gentagne gange spørger "har jeg set denne?", er en mængde det rigtige værktøj. Forskellen i hastighed vokser markant, efterhånden som samlingen bliver stor.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var ids = new HashSet<int> { 10, 20, 30 };
Console.WriteLine(ids.Contains(20)); // True
Console.WriteLine(ids.Contains(99)); // False
}
}Fjernelse af dubletter fra en List
En almindelig opgave er at tage en liste og kun beholde unikke værdier. Hvis du opretter en HashSet ud fra listen, klarer du det i O(n).
Den resulterende mængde indeholder hver værdi én gang. Hvis du har brug for en liste igen, kan du oprette den sådan: new List<int>(set).
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var nums = new List<int> { 1, 2, 2, 3, 3, 3 };
var unique = new HashSet<int>(nums);
Console.WriteLine(unique.Count); // 3
}
}Foreningsmængde
UnionWith tilføjer hvert element fra en anden samling og springer dubletter over. Resultatet indeholder alt fra begge samlinger.
Det ændrer mængden direkte. Det er langt renere end selv at gennemløbe samlingen og kalde Add for hvert element.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var a = new HashSet<int> { 1, 2, 3 };
a.UnionWith(new[] { 3, 4, 5 });
Console.WriteLine(a.Count); // 5
}
}Fællesmængde
IntersectWith beholder kun de elementer, der også findes i den anden samling, og fjerner resten.
Brug den til at finde fælles elementer, f.eks. tags, som deles af to artikler, eller brugere, der findes i begge grupper.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var a = new HashSet<int> { 1, 2, 3, 4 };
a.IntersectWith(new[] { 2, 4, 6 });
Console.WriteLine(string.Join(",", a)); // 2,4
}
}Mængdedifference
ExceptWith fjerner alle elementer fra mængden, som findes i den anden samling, så det, der er unikt for mængden, bliver tilbage.
Det er mængdedifferensoperationen: "elementer i A, men ikke i B". Det er velegnet til at beregne, hvad der er ændret, eller hvad der mangler at blive behandlet.
var a = new HashSet<int> { 1, 2, 3, 4 };
a.ExceptWith(new[] { 2, 4 });
// a now contains 1 and 3Delmængde og supermængde
IsSubsetOf og IsSupersetOf tester indeholdelsesrelationer mellem mængder og returnerer en bool.
Overlaps tjekker, om mindst ét element er fælles, og SetEquals tester, om to mængder indeholder præcis de samme elementer, uanset rækkefølgen.
var a = new HashSet<int> { 1, 2 };
var b = new HashSet<int> { 1, 2, 3 };
bool sub = a.IsSubsetOf(b); // true
bool ov = a.Overlaps(b); // trueLighed mellem elementer
Unikhed afhænger af GetHashCode og Equals for elementtypen, præcis som for ordbogsnøgler.
For brugerdefinerede typer skal du tilsidesætte begge metoder eller bruge en record. Ellers behandles to logisk ens objekter som forskellige, og begge ender i mængden.
var names = new HashSet<string>(
System.StringComparer.OrdinalIgnoreCase);
names.Add("Sam");
bool dup = !names.Add("SAM"); // true: treated as sameIngen indeksering eller rækkefølge
En HashSet har ingen adgang via indeks; du kan ikke skrive set[0]. Du kan kun gennemløbe den med foreach.
Gennemløbsrækkefølgen er ikke garanteret. Hvis du har brug for både unikhed og sorteret rækkefølge, skal du bruge SortedSet<T>, som holder elementerne sorteret til en pris af O(log n) for operationerne.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var s = new SortedSet<int> { 3, 1, 2 };
Console.WriteLine(string.Join(",", s)); // 1,2,3
}
}Sporing af sete elementer
Et almindeligt mønster er at filtrere en datastrøm, så hver værdi kun forekommer én gang. Føj værdien til en mængde, og gør kun noget, når Add returnerer true.
Det er renere og hurtigere end at tjekke en voksende liste og omdanner en gennemgang i O(n i anden) til O(n).
using System;
using System.Collections.Generic;
class Program {
static void Main() {
var seen = new HashSet<int>();
foreach (int x in new[] { 1, 1, 2, 3, 2 })
if (seen.Add(x)) Console.Write(x + " ");
// prints 1 2 3
}
}Hurtigt tjek
Husk, hvad en HashSet håndhæver, og hvad opslagsomkostningen er.
Opsummering
HashSet<T> gemmer unikke værdier og har i gennemsnit O(1) for tilføjelse, fjernelse og medlemskabstjek, men ingen rækkefølge eller indeksering.
Den er særligt velegnet til fjernelse af dubletter, hurtige "har jeg set denne?"-tjek og mængdealgebra via UnionWith, IntersectWith og ExceptWith. Brugerdefinerede elementtyper skal have korrekt lighed.
Lær C# med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 93
- Lektioner
- 346
Ofte stillede spørgsmål
Er lektionen “HashSet og entydighed” gratis?
Ja — hele teksten til “HashSet og entydighed” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C# Academy-kurset, skal du opgradere til CoddyKit PRO. C# Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “HashSet og entydighed”?
Hold styr på forskellige værdier. Du øver dig i C# Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på C# Academy?
Der kræves ingen tidligere erfaring. C# Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “HashSet og entydighed”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne C# Academy-lektion?
Ja. Alle C# Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- List i praksis
- Opslag i Dictionary
- HashSet og entydighed
- Vælg en samling