0Pricing
C# Academy · Lezione

HashSet e unicità

Tenga traccia dei valori distinti.

HashSet e unicità è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.

Che cos'è un HashSet?

HashSet<T> memorizza una raccolta di valori univoci, senza duplicati. L'aggiunta di un valore già presente non produce alcun effetto.

Come un dizionario, si basa su una tabella hash, quindi i controlli di appartenenza hanno complessità media O(1). Non mantiene l'ordine di inserimento.

using System.Collections.Generic;

var seen = new HashSet<int>();
seen.Add(1);
seen.Add(1); // ignored, still one element

Add restituisce un booleano

Add restituisce true se il valore era nuovo e false se era già presente.

Questo valore restituito è utile per rilevare i duplicati in un unico passaggio, senza un controllo separato con Contains.

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
    }
}

Controlli rapidi di appartenenza

Contains su un HashSet ha complessità media O(1), rispetto a O(n) su una List.

Quando chiede ripetutamente «ho già visto questo valore?», un set è lo strumento giusto. La differenza di velocità aumenta notevolmente quando la raccolta diventa grande.

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
    }
}

Rimozione dei duplicati da una lista

Un'attività comune consiste nel prendere una lista e conservare solo i valori distinti. La costruzione di un HashSet a partire dalla lista svolge questa operazione in O(n).

Il set risultante contiene ogni valore una sola volta. Se le serve nuovamente una lista, la avvolga così: 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
    }
}

Unione

UnionWith aggiunge ogni elemento di un'altra raccolta, ignorando i duplicati. Il risultato contiene tutti gli elementi di entrambe.

Questa operazione modifica direttamente il set. È molto più pulita rispetto a un ciclo che chiama Add manualmente per ogni elemento.

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
    }
}

Intersezione

IntersectWith conserva solo gli elementi presenti anche nell'altra raccolta e rimuove tutti gli altri.

La utilizzi per trovare gli elementi comuni, ad esempio i tag condivisi da due articoli o gli utenti appartenenti a entrambi i gruppi.

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
    }
}

Differenza

ExceptWith rimuove dal set ogni elemento presente nell'altra raccolta, lasciando quelli esclusivi del set.

È l'operazione di differenza tra insiemi: «gli elementi in A ma non in B». È ideale per calcolare che cosa è cambiato o che cosa resta da elaborare.

var a = new HashSet<int> { 1, 2, 3, 4 };
a.ExceptWith(new[] { 2, 4 });
// a now contains 1 and 3

Sottoinsieme e sovrainsieme

IsSubsetOf e IsSupersetOf verificano le relazioni di contenimento tra set e restituiscono un bool.

Overlaps verifica se è condiviso almeno un elemento, mentre SetEquals controlla se due set contengono esattamente gli stessi elementi, indipendentemente dall'ordine.

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);      // true

Uguaglianza degli elementi

L'unicità dipende da GetHashCode e Equals del tipo degli elementi, esattamente come per le chiavi dei dizionari.

Per i tipi personalizzati, esegua l'override di entrambi i metodi oppure utilizzi un record; in caso contrario, due oggetti logicamente uguali vengono trattati come distinti e finiscono entrambi nel set.

var names = new HashSet<string>(
    System.StringComparer.OrdinalIgnoreCase);
names.Add("Sam");
bool dup = !names.Add("SAM"); // true: treated as same

Nessun indice né ordine

Un HashSet non consente l'accesso tramite indice: non può scrivere set[0]. Può solo enumerarlo con foreach.

L'ordine di enumerazione non è garantito. Se le servono sia l'unicità sia l'ordine ordinato, utilizzi SortedSet<T>, che mantiene gli elementi ordinati al costo di operazioni O(log n).

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
    }
}

Tracciamento degli elementi già visti

Un modello frequente consiste nel filtrare un flusso in modo che ogni valore compaia una sola volta. Aggiunga ogni valore a un set e agisca solo quando Add restituisce true.

È più pulito e veloce che controllare una lista in continua crescita, trasformando una scansione O(n al quadrato) in 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
    }
}

Verifica rapida

Ricordi quali vincoli impone un HashSet e qual è il costo delle sue ricerche.

Riepilogo

HashSet<T> memorizza valori univoci e offre, in media, operazioni O(1) di aggiunta, rimozione e controllo di appartenenza, ma non supporta ordine né indicizzazione.

È particolarmente utile per rimuovere duplicati, verificare rapidamente «ho già visto questo valore?» e applicare operazioni tra insiemi tramite UnionWith, IntersectWith ed ExceptWith. I tipi di elemento personalizzati richiedono una corretta implementazione dell'uguaglianza.

Domande Frequenti

La lezione «HashSet e unicità» è gratuita?

Sì — il testo completo di «HashSet e unicità» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.

Cosa imparerò in «HashSet e unicità»?

Tenga traccia dei valori distinti. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C# Academy?

Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «HashSet e unicità»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C# Academy?

Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Le liste nella pratica
  2. Ricerche nei dizionari
  3. HashSet e unicità
  4. Scegliere una collezione
← Torna a C# Academy