pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
contents
.lines()
.filter(|line| line.contains(query))
.collect()
}
Listing 13-22: Using iterator adaptor methods in the implementation of the `search` function
Recall that the purpose of the `search` function is to return all lines in `contents` that contain the `query`. Similar to the `filter` example in Listing 13-16, this code uses the `filter` adaptor to keep only the lines that `line.contains(query)` returns `true` for. We then collect the matching lines into another vector with `collect`. **Much simpler! Feel free to make the same change to use iterator methods in the `search_case_insensitive` function as well.**
The way I see it, this cannot be done unless one is setting each line to lower case first as in the original code from chapter 12, such as
for line in content.lines() {
if line.to_lowercase().contains(&query) {
results.push(line);
}
}
results
.lines()
.filter(|line| line.contains(query))
.collect()
Using the lines() with a map(|line| line.to_lowercase()) is not possible
I think the confusion is because there are multiple versions of that code snippet. The code they're referring to from chapter 12 is a version before they added case insensitive matching. In the text you quoted, the last sentence says they're leaving it up to you to integrate with the case insensitive matching version.
Recall that the purpose of the search function is to return all lines in contents that contain the query. Similar to the filter example in Listing 13-16, this code uses the filter adaptor to keep only the lines that line.contains(query) returns true for. We then collect the matching lines into another vector with collect. Much simpler! Feel free to make the same change to use iterator methods in the search_case_insensitive function as well.
Yes, they are leaving up to the user. But if one is doing so, they still have to put the contents into lower case, which cannot be done using an iterator with map. So, I am wondering if it is worth integrating that in after a new Vec is generated with lower case contents.
What makes you say that? The only impediment to that approach is the fact that you'd have to change the return type from Vec<&'a str> to Vec<String>, like so:
Alternatively, you can keep the return type by doing the to_lowercase() inside the .filter():
This is what makes me say so, but then again I'm still in the noobie phase:
note: the method call chain might not have had the expected associated types
--> src/lib.rs:85:10
|
84 | content
| ------- this expression has type `&str`
85 | .lines()
| ^^^^^^^ `Iterator::Item` is `&str` here
86 | .filter(|line| line.to_lowercase().contains(&*query))
| ---------------------------------------------------- `Iterator::Item` remains `&str` here
note: required by a bound in `collect`