BTreeSet::range în Rust

Parcurge doar elementele dintr-un interval de valori, în ordine; util pentru „următorul după x” sau „toate dintre a și b”.

Sintaxă
pub fn range<K: ?Sized, R>(&self, range: R) -> Range<'_, T>
where K: Ord, T: Borrow<K> + Ord, R: RangeBounds<K>

Ce face BTreeSet::range

range(a..b) dă elementele mulțimii cuprinse între a (inclusiv) și b (exclusiv), crescător. Merg toate formele de interval. Începutul este găsit rapid, fără parcurgerea întregii mulțimi.

Două întrebări foarte frecvente se rezolvă cu el: „care este primul element cel puțin egal cu x?” (range(x..).next()) și „care este ultimul element mai mic decât x?” (range(..x).next_back()).

Parametri

Parametru Descriere
range Intervalul de valori.

Ce returnează

Un iterator de &T, în ordine crescătoare.

Exemple

Exemplul 1: Următorul autobuz

Orele de plecare sunt ținute în minute de la miezul nopții.

use std::collections::BTreeSet;

fn ora(m: u32) -> String {
    format!("{:02}:{:02}", m / 60, m % 60)
}

fn main() {
    let plecari: BTreeSet<u32> = [6 * 60 + 15, 7 * 60, 8 * 60 + 30, 12 * 60, 14 * 60 + 45, 17 * 60 + 10, 21 * 60].into();
    for acum in [7 * 60, 13 * 60 + 5, 22 * 60] {
        match plecari.range(acum..).next() {
            Some(&p) => println!("la {}: următorul autobuz pleacă la {}", ora(acum), ora(p)),
            None => println!("la {}: nu mai sunt autobuze azi", ora(acum)),
        }
    }
    let dimineata: Vec<String> = plecari.range(..12 * 60).map(|&m| ora(m)).collect();
    println!("dimineața: {}", dimineata.join(", "));
}

Rezultat

la 07:00: următorul autobuz pleacă la 07:00
la 13:05: următorul autobuz pleacă la 14:45
la 22:00: nu mai sunt autobuze azi
dimineața: 06:15, 07:00, 08:30

Exemplul 2: Sugestii după prefix

Pornim de la prefix și ne oprim la primul cuvânt care nu mai începe cu el.

use std::collections::BTreeSet;

fn main() {
    let cuvinte: BTreeSet<&str> = ["mare", "masă", "mașină", "mama", "mere", "mic", "munte", "lac"].into();
    for prefix in ["ma", "mu", "x"] {
        let sugestii: Vec<&str> = cuvinte
            .range(prefix..)
            .take_while(|c| c.starts_with(prefix))
            .copied()
            .collect();
        println!("{prefix}: {:?}", sugestii);
    }
}

Rezultat

ma: ["mama", "mare", "masă", "mașină"]
mu: ["munte"]
x: []

Greșeli frecvente

  • Interval invers (range(10..5)): panic.
  • Folosești iter().find(|&&x| x >= acum): corect, dar parcurge de la început. range(acum..).next() sare direct.

Comenzi înrudite

  • BTreeSet: Mulțime cu elementele mereu sortate: fără duplicate, ca HashSet, dar parcurgerea este în ordine crescătoare.
  • BTreeMap::range: Parcurge doar perechile cu cheile într-un interval (a..b, a..=b, a.., ..b), în ordine crescătoare.
  • BTreeSet::first: Returnează cel mai mic (first) sau cel mai mare (last) element al mulțimii sortate; None dacă e goală.
  • Range: Intervalul a..b: toate valorile de la a inclusiv până la b exclusiv. Este iterator, se folosește în for și la tăierea slice-urilor.
  • Iterator::take_while: take_while dă elemente cât timp condiția e adevărată și se oprește la primul care nu o îndeplinește; skip_while sare până atunci.