HashSet::union în Rust

Operațiile cu mulțimi: reuniune (în oricare), intersecție (în ambele), diferență (doar în prima), diferență simetrică (în exact una).

Sintaxă
pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S>
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S>
pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S>
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>) -> SymmetricDifference<'a, T, S>

Ce face HashSet::union

a.union(&b) dă elementele care sunt în a sau în b (fiecare o dată). a.intersection(&b) dă elementele comune. a.difference(&b) dă elementele din a care nu sunt în b (ordinea contează: b.difference(&a) e altceva). a.symmetric_difference(&b) dă elementele care sunt în exact una dintre ele.

Toate returnează iteratori leneși de referințe (&T), care nu creează o mulțime nouă. Colectează-i cu .collect(), sau, pentru valori Copy, .copied().collect(). Variantele cu operatori creează direct o mulțime nouă: &a | &b, &a & &b, &a - &b, &a ^ &b.

Ordinea rezultatelor este aleatorie; sortează pentru afișare sau folosește BTreeSet, care are aceleași metode și dă rezultatele sortate.

Parametri

Parametru Descriere
other A doua mulțime (prin referință).

Ce returnează

Un iterator de &T.

Exemple

Exemplul 1: Olimpiade la română și la mate

use std::collections::HashSet;

fn sortat<'a>(elemente: impl Iterator<Item = &'a &'static str>) -> Vec<&'static str> {
    let mut v: Vec<&'static str> = elemente.copied().collect();
    v.sort();
    v
}

fn main() {
    let romana: HashSet<&str> = HashSet::from(["Ana", "Mihai", "Ioana", "Radu"]);
    let mate: HashSet<&str> = HashSet::from(["Mihai", "Elena", "Radu", "Paul"]);

    println!("la cel puțin una:  {:?}", sortat(romana.union(&mate)));
    println!("la amândouă:       {:?}", sortat(romana.intersection(&mate)));
    println!("doar la română:    {:?}", sortat(romana.difference(&mate)));
    println!("doar la mate:      {:?}", sortat(mate.difference(&romana)));
    println!("la exact una:      {:?}", sortat(romana.symmetric_difference(&mate)));
}

Rezultat

la cel puțin una:  ["Ana", "Elena", "Ioana", "Mihai", "Paul", "Radu"]
la amândouă:       ["Mihai", "Radu"]
doar la română:    ["Ana", "Ioana"]
doar la mate:      ["Elena", "Paul"]
la exact una:      ["Ana", "Elena", "Ioana", "Paul"]

Exemplul 2: Operatorii | & – ^ creează mulțimi noi

Afișăm prin BTreeSet, ca rezultatul să fie sortat.

use std::collections::{BTreeSet, HashSet};

fn main() {
    let a: HashSet<u32> = HashSet::from([1, 2, 3, 4]);
    let b: HashSet<u32> = HashSet::from([3, 4, 5]);

    let sortat = |s: HashSet<u32>| s.into_iter().collect::<BTreeSet<u32>>();
    println!("a | b = {:?}", sortat(&a | &b));
    println!("a & b = {:?}", sortat(&a & &b));
    println!("a - b = {:?}", sortat(&a - &b));
    println!("a ^ b = {:?}", sortat(&a ^ &b));
}

Rezultat

a | b = {1, 2, 3, 4, 5}
a & b = {3, 4}
a - b = {1, 2}
a ^ b = {1, 2, 5}

Exemplul 3: Cine lipsește azi

use std::collections::HashSet;

fn main() {
    let clasa: HashSet<&str> = ["Ana", "Mihai", "Ioana", "Radu", "Elena"].into_iter().collect();
    let prezenti: HashSet<&str> = ["Mihai", "Elena", "Ana"].into_iter().collect();

    let mut absenti: Vec<&str> = clasa.difference(&prezenti).copied().collect();
    absenti.sort();
    println!("absenți: {}", absenti.join(", "));
    println!("{} din {} prezenți", clasa.intersection(&prezenti).count(), clasa.len());
}

Rezultat

absenți: Ioana, Radu
3 din 5 prezenți

Greșeli frecvente

  • Te aștepți ca union să returneze un HashSet: returnează un iterator de referințe. Adaugă .cloned().collect::<HashSet<_>>() sau folosește operatorul &a | &b.
  • Inversezi argumentele la difference: a.difference(&b) înseamnă „ce are a și nu are b”.
  • Folosești operatorii fără &: a | b nu compilează pentru HashSet; scrie &a | &b.

Comenzi înrudite

  • HashSet: O mulțime: ține fiecare valoare o singură dată și răspunde foarte repede dacă o valoare există. Ordinea nu e garantată.
  • HashSet::is_subset: Verifică dacă toate elementele unei mulțimi se află și în alta; is_superset și is_disjoint sunt verificările înrudite.
  • HashSet::iter: Parcurge elementele mulțimii prin referință, într-o ordine aleatorie; pentru afișare stabilă, colectează și sortează.
  • BTreeSet: Mulțime cu elementele mereu sortate: fără duplicate, ca HashSet, dar parcurgerea este în ordine crescătoare.
  • Iterator::collect: Consumă iteratorul și adună valorile într-o colecție: Vec, String, HashMap, HashSet, chiar Result sau Option.