Ce face Iterator::take_while
take_while(|x| cond) produce elemente până la primul pentru care condiția este falsă, apoi se oprește definitiv, chiar dacă mai târziu ar urma elemente care o îndeplinesc. skip_while(|x| cond) face complementul: sare peste elemente cât timp condiția e adevărată, apoi le dă pe toate celelalte, fără să mai verifice condiția.
Diferența față de filter: filter verifică fiecare element; take_while și skip_while privesc doar „începutul” șirului. Sunt potrivite pentru date sortate sau pentru prefixe (cifrele de la începutul unui text, liniile de antet). Ca la filter, closure-ul primește o referință. Ca toate adaptoarele, este leneș: nu face nimic până când iteratorul nu este consumat (de for, collect, sum, count etc.).
Parametri
| Parametru | Descriere |
|---|---|
predicate |
Condiția verificată pe &element. |
Ce returnează
Un iterator TakeWhile sau SkipWhile.
Exemple
Exemplul 1: Comparație cu filter
take_while se oprește la 12, deci nu ajunge la 3 și 4 de la final; filter îi găsește.
fn main() {
let v = [1, 4, 7, 12, 3, 4];
let tw: Vec<i32> = v.iter().copied().take_while(|&x| x < 10).collect();
let sw: Vec<i32> = v.iter().copied().skip_while(|&x| x < 10).collect();
let f: Vec<i32> = v.iter().copied().filter(|&x| x < 10).collect();
println!("take_while: {:?}", tw);
println!("skip_while: {:?}", sw);
println!("filter: {:?}", f);
}
Rezultat
take_while: [1, 4, 7]
skip_while: [12, 3, 4]
filter: [1, 4, 7, 3, 4]
Exemplul 2: Numărul de la începutul unui text
fn main() {
for text in ["42 de elevi", "7kg", "fără număr"] {
let cifre: String = text.chars().take_while(|c| c.is_ascii_digit()).collect();
let rest: String = text.chars().skip_while(|c| c.is_ascii_digit()).collect();
println!("{text:12} -> număr: {:?}, rest: {:?}", cifre, rest.trim());
}
}
Rezultat
42 de elevi -> număr: "42", rest: "de elevi"
7kg -> număr: "7", rest: "kg"
fără număr -> număr: "", rest: "fără număr"
Exemplul 3: Comenzi de azi dintr-o listă sortată după oră
fn main() {
// (ora, client), sortate după oră
let comenzi = [(8, "Ana"), (9, "Mihai"), (11, "Ioana"), (14, "Radu"), (17, "Elena")];
let dimineata: Vec<&str> = comenzi.iter().take_while(|(ora, _)| *ora < 12).map(|(_, c)| *c).collect();
let dupa_amiaza: Vec<&str> = comenzi.iter().skip_while(|(ora, _)| *ora < 12).map(|(_, c)| *c).collect();
println!("dimineața: {:?}", dimineata);
println!("după-amiaza: {:?}", dupa_amiaza);
}
Rezultat
dimineața: ["Ana", "Mihai", "Ioana"]
după-amiaza: ["Radu", "Elena"]
Greșeli frecvente
- Folosești
take_whilepe date nesortate și te aștepți să găsească toate elementele care îndeplinesc condiția. Se oprește la primul care nu o îndeplinește; pentru toate foloseștefilter. - Elementul care oprește
take_whileeste consumat din sursă și pierdut. Dacă îl vrei înapoi, foloseștepeekable()cunext_if.
Comenzi înrudite
Iterator::take: take(n) produce cel mult primele n elemente; skip(n) sare peste primele n și produce restul.Iterator::map_while: Transformă elementele cât timp funcția returnează Some și se oprește la primul None.Iterator::filter: Păstrează doar elementele pentru care condiția dată returnează true; restul sunt sărite.Iterator::peekable: Transformă iteratorul într-un Peekable, care te lasă să te uiți la următorul element (peek) fără să-l consumi.BTreeSet::range: Parcurge doar elementele dintr-un interval de valori, în ordine; util pentru „următorul după x” sau „toate dintre a și b”.