Rust - 从 `&str` 转换为 `String` 并使用闭包返回

Gat*_*tes 1 closures ownership rust borrow-checker borrowing

我正在阅读这本书,但我不明白为什么这个函数不能编译:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents
        .lines()                           // Fetch an iterator for each line in `contents`
        .map(|x| x.to_lowercase())         // (x is now String) Convert each line to lowercase
        .filter(|x| x.contains(query))     // Filter out lines that do not contain query
        .map(|x| x.trim())                 // Eliminate extra whitespace
        .collect()                         // Consume iterator and produce Vec<&str>
}
Run Code Online (Sandbox Code Playgroud)

如果没有该to_lowercase()行,它将运行,我猜这是因为它将返回 aString而不是&str我们最后需要输出的。但是,当我将转换替换回&strlike 时:

// -- snip --
.map(|x| x.to_lowercase().to_str())
// -- snip --
Run Code Online (Sandbox Code Playgroud)

这表明正在引用临时值。我认为&str这是因为引用了String,当发布时它也String会使我无效。&str

闭包是否不是处理这个问题的好方法,我应该将其分成不同的语句?

kfe*_*v91 5

这表明正在引用临时值。我认为&str这是因为引用了String,当发布时它也String会使我无效。&str

这个假设是正确的。

闭包是否不是处理这个问题的好方法,我应该将其分成不同的语句?

to_lowercase()该函数进行再多的重构都不会改变需要修改&str且 必须生成 的事实String,因此,如果需要小写内容,那么这是您可以做的最好的事情:

fn search(query: &str, contents: &str) -> Vec<String> {
    contents
        .lines()                           // Fetch an iterator for each line in contents
        .map(|x| x.trim().to_lowercase())  // Trim & lowercase string
        .filter(|x| x.contains(query))     // Filter out lines that do not contain query
        .collect()                         // Consume iterator and produce Vec<String>
}
Run Code Online (Sandbox Code Playgroud)

如果你想执行不区分大小写的过滤,但仍然返回未修改的内容(不小写),那么你可以这样做:

fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    contents
        .lines()                                        // Fetch an iterator for each line in contents
        .filter(|x| x.to_lowercase().contains(query))   // Filter out lines that do not contain query
        .map(|x| x.trim())                              // Trim whitesapce
        .collect()                                      // Consume iterator and produce Vec<&'a str>
}
Run Code Online (Sandbox Code Playgroud)