CodeBlanks Logo Icon CodeBlanks

Processing with iterators

Chain commands with iterators.

Processing with iterators

The search command must filter the notes together with their numbers. An enumerate and filter chain does this without building an intermediate collection:

impl Defter {
    fn ara(&self, sorgu: &str) -> Vec<(usize, &String)> {
        let s = sorgu.to_lowercase();
        self.notlar
            .iter()
            .enumerate()
            .filter(|(_, n)| n.to_lowercase().contains(&s))
            .map(|(i, n)| (i + 1, n))
            .collect()
    }
}

Adding the number before filter matters; otherwise the displayed number wouldn't reflect the note's real position.

Summary statistics

Iterators are ideal for short reports too:

let toplam_karakter: usize = d.notlar.iter().map(|n| n.chars().count()).sum();
let en_uzun = d.notlar.iter().max_by_key(|n| n.chars().count());
println!("{} not, {} karakter, en uzun: {:?}",
    d.notlar.len(), toplam_karakter, en_uzun);

Practice Search notes

Add the ara method to Defter. Add the notes "süt al", "kod yaz" and "süt faturası", and print the results of ara("süt") as N. note.

Starter code

main.rs
struct Defter {
    notlar: Vec<String>,
}

impl Defter {
    fn new() -> Self {
        Self { notlar: Vec::new() }
    }
    fn ekle(&mut self, metin: String) {
        self.notlar.push(metin);
    }
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
struct Defter {
    notlar: Vec<String>,
}

impl Defter {
    fn new() -> Self {
        Self { notlar: Vec::new() }
    }
    fn ekle(&mut self, metin: String) {
        self.notlar.push(metin);
    }
}

impl Defter {
    fn ara(&self, sorgu: &str) -> Vec<(usize, &String)> {
        let s = sorgu.to_lowercase();
        self.notlar
            .iter()
            .enumerate()
            .filter(|(_, n)| n.to_lowercase().contains(&s))
            .map(|(i, n)| (i + 1, n))
            .collect()
    }
}

fn main() {
    let mut d = Defter::new();
    for n in ["süt al", "kod yaz", "süt faturası"] {
        d.ekle(n.to_string());
    }
    for (i, n) in d.ara("süt") {
        println!("{}. {}", i, n);
    }
}

Expected output

1. süt al
3. süt faturası

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What would happen if <code>enumerate</code> were called after <code>filter</code>?

  • Numbers would count 1, 2, 3 among the matches only Correct answer
  • Compile error
  • The result wouldn't change
  • Panic

Explanation: The order of adapters changes the meaning; since the delete command needs the real number, enumerate must come first.

2 Filter the matches

Question
.enumerate()
.____(|(_, n)| n.to_lowercase().contains(&s))
Answer
.enumerate()
.filter(|(_, n)| n.to_lowercase().contains(&s))

Explanation: filter keeps the (number, note) pairs that meet the condition.

3 Query and matching numbers

Term Meaning
"süt" 1, 3
"KOD" 2
"fatura" 3
"çay" None

All lessons in Intermediate