Rust - 从 `&str` 转换为 `String` 并返回闭包
Rust - Converting from `&str` to `String` and back with Closures
我正在研究 book,但我不明白为什么这个函数不能编译:
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>
}
如果没有 to_lowercase()
行,它将 运行,我猜那是因为那将是 return 一个 String
而不是 &str
我们需要在最后输出。但是,当我将转换替换回 &str
时,例如:
// -- snip --
.map(|x| x.to_lowercase().to_str())
// -- snip --
这表明正在引用一个临时值。我认为这是因为 &str
引用了 String
,当 String
被释放时它也使我的 &str
无效。
闭包不是处理这个问题的好方法吗,我应该把它分成不同的语句吗?
This states that a temporary value is being referenced. Which I assume because &str
reference the String
, when the String
is released it makes my &str
invalid as well.
这个假设是正确的。
Are closures just not a good way of handling this, and I should break it into different statement?
该函数再多的重构也不会改变 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>
}
如果你想执行不区分大小写的过滤但仍然return未修改的内容(没有小写)那么你可以这样做:
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>
}
对于跟在我后面的人来说,这是我结束的地方。谢谢@pretzelhammer。
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase(); // transform query to lowercase()
contents
.lines()
.filter(|x| x.to_lowercase().contains(&query))
.map(|x| x.trim())
.collect()
}
我正在研究 book,但我不明白为什么这个函数不能编译:
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>
}
如果没有 to_lowercase()
行,它将 运行,我猜那是因为那将是 return 一个 String
而不是 &str
我们需要在最后输出。但是,当我将转换替换回 &str
时,例如:
// -- snip --
.map(|x| x.to_lowercase().to_str())
// -- snip --
这表明正在引用一个临时值。我认为这是因为 &str
引用了 String
,当 String
被释放时它也使我的 &str
无效。
闭包不是处理这个问题的好方法吗,我应该把它分成不同的语句吗?
This states that a temporary value is being referenced. Which I assume because
&str
reference theString
, when theString
is released it makes my&str
invalid as well.
这个假设是正确的。
Are closures just not a good way of handling this, and I should break it into different statement?
该函数再多的重构也不会改变 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>
}
如果你想执行不区分大小写的过滤但仍然return未修改的内容(没有小写)那么你可以这样做:
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>
}
对于跟在我后面的人来说,这是我结束的地方。谢谢@pretzelhammer。
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase(); // transform query to lowercase()
contents
.lines()
.filter(|x| x.to_lowercase().contains(&query))
.map(|x| x.trim())
.collect()
}