Listing records
- Rust course
- Intermediate
- Lesson 110/115
- 6 min
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
#[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
#[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?
.filter(|y| y.etiketler.iter().____(|e| e == etiket))
.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 |