CodeBlanks Logo Icon CodeBlanks

Listing records

Produce a post list with an iterator.

Listing records

Queries on the loaded posts are built with iterator chains. Each query is a predicate closure and they can be combined:

fn yayindakiler<'a>(v: &'a [Yazi], etiket: &str) -> Vec<&'a Yazi> {
    v.iter()
        .filter(|y| y.yayinda)
        .filter(|y| y.etiketler.iter().any(|e| e == etiket))
        .collect()
}

The result is a vector of references; the posts aren't copied. Since the return's lifetime is tied to the input slice, 'a is written.

Sorting and summary

A vector of references can be sorted too; by topic with sort_by_key:

let mut liste = yayindakiler(&yazilar, "rust");
liste.sort_by_key(|y| y.konu.clone());
for y in &liste {
    println!("{}. {} ({})", y.id, y.konu, y.yazar);
}

sort_by(|a, b| a.konu.cmp(&b.konu)) does the same without cloning.

Practice Published Rust posts

With the ready veri_seti() data, write the yayindakiler function above. Print the published posts tagged "rust" as id. topic (author).

Starter code

main.rs
#[derive(Debug, Clone)]
struct Yazi {
    id: u32,
    konu: String,
    yazar: String,
    etiketler: Vec<String>,
    yayinda: bool,
}

fn veri_seti() -> Vec<Yazi> {
    let y = |id, konu: &str, yazar: &str, et: &[&str], yayinda| Yazi {
        id,
        konu: konu.to_string(),
        yazar: yazar.to_string(),
        etiketler: et.iter().map(|e| e.to_string()).collect(),
        yayinda,
    };
    vec![
        y(1, "Rust ile başlangıç", "ece", &["rust", "giriş"], true),
        y(2, "Sahiplik", "can", &["rust"], false),
        y(3, "Web sunucusu", "ece", &["rust", "web"], true),
        y(4, "Python notları", "ali", &["python"], true),
    ]
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
#[derive(Debug, Clone)]
struct Yazi {
    id: u32,
    konu: String,
    yazar: String,
    etiketler: Vec<String>,
    yayinda: bool,
}

fn veri_seti() -> Vec<Yazi> {
    let y = |id, konu: &str, yazar: &str, et: &[&str], yayinda| Yazi {
        id,
        konu: konu.to_string(),
        yazar: yazar.to_string(),
        etiketler: et.iter().map(|e| e.to_string()).collect(),
        yayinda,
    };
    vec![
        y(1, "Rust ile başlangıç", "ece", &["rust", "giriş"], true),
        y(2, "Sahiplik", "can", &["rust"], false),
        y(3, "Web sunucusu", "ece", &["rust", "web"], true),
        y(4, "Python notları", "ali", &["python"], true),
    ]
}

fn yayindakiler<'a>(v: &'a [Yazi], etiket: &str) -> Vec<&'a Yazi> {
    v.iter()
        .filter(|y| y.yayinda)
        .filter(|y| y.etiketler.iter().any(|e| e == etiket))
        .collect()
}

fn main() {
    let yazilar = veri_seti();
    for y in yayindakiler(&yazilar, "rust") {
        println!("{}. {} ({})", y.id, y.konu, y.yazar);
    }
}

Expected output

1. Rust ile başlangıç (ece)
3. Web sunucusu (ece)

Questions and answers

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

1 Why is a lifetime annotation needed here?

  • It isn't needed
  • There are two reference parameters; it's unclear which the return depends on Correct answer
  • Vec needs a lifetime
  • filter needs a lifetime

Explanation: Elision rules can't determine the return lifetime with two reference parameters; we state explicitly that it depends on v.

2 Is the tag there?

Question
.filter(|y| y.etiketler.iter().____(|e| e == etiket))
Answer
.filter(|y| y.etiketler.iter().any(|e| e == etiket))

Explanation: any returns true if at least one element meets the condition.

3 Query and result (sample data)

Term Meaning
published + "rust" 1, 3
published + "python" 4
not published 2
"web" 3

All lessons in Intermediate