我正在使用chapter 12 of The Rust Programming Language ,其中实现了不区分大小写的行搜索。对我来说两次实现相同的逻辑是没有意义的,所以我想如果我只是调用区分大小写的搜索函数并将参数转换为小写,那可能会起作用。它没。
这是我的非工作代码:
fn main() {
let a = search("Waldo", "where in\nthe world\nis Waldo?");
let b = search("waldo", "where in\nthe world\nis Waldo?");
let c = search_case_insensitive("waldo", "where in\nthe world\nis Waldo?");
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
}
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut results = Vec::new();
for line in contents.lines() {
if line.contains(query) {
results.push(line);
}
}
results
}
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase();
let contents2: &str = &contents.to_lowercase();
search(&query, contents2)
}
我提出的大多数版本中的错误都不可避免地非常类似于:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:25:28
|
25 | let contents2: &str = &contents.to_lowercase();
| ^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
...
28 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 23:1...
--> src/main.rs:23:1
|
23 | pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
最佳答案
编辑2:
既然您已经用 MCVE 更新了问题,并且您已经声明您不关心偏离书中的示例...这是另一个版本,依赖于通过使用 String< 进行额外分配
:
fn main() {
let a = search("Waldo", "where in\nthe world\nis Waldo?");
let b = search("waldo", "where in\nthe world\nis Waldo?");
let c = search_case_insensitive("waldo", "where in\nthe world\nis Waldo?");
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
}
pub fn search<S>(query: S, contents: S) -> Vec<String> where S: Into<String> {
let query = query.into();
let mut results = Vec::new();
for line in contents.into().lines() {
if line.contains(&query) {
results.push(line.into());
}
}
results
}
pub fn search_case_insensitive<S>(query: S, contents: S) -> Vec<String> where S: Into<String> {
let query = query.into().to_lowercase();
let contents = contents.into().to_lowercase();
search(query, contents)
}
编辑:
我意识到我从未真正给过你替代方案。这是我可能会做的:
pub enum SearchOptions {
CaseSensitive,
CaseInsensitive
}
pub fn search<'a>(query: &str, contents: &'a str, options: SearchOptions) -> Vec<&'a str> {
let mut results = Vec::new();
for line in contents.lines() {
let check = match options {
SearchOptions::CaseSensitive => line.contains(query),
SearchOptions::CaseInsensitive => line.to_lowercase().contains(&query.to_lowercase()),
};
if check {
results.push(line);
}
}
results
}
这就是您可以对其进行“重复数据删除”的最大程度了。
原始答案:
实际的问题是,当内容
绑定(bind)到生命周期'a
时,您试图传递它......但您真正想要的是什么“不区分大小写”是查询
。
这并不以完全相同的方式绑定(bind)到生命周期'a
,因此......有效:
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase();
search(&query, contents)
}
尽管如此,您仍然需要复制逻辑...因为您需要将小写查询与小写行相匹配...这在书中的示例中进行了演示:
if line.to_lowercase().contains(&query) {
// ^^^^^^^^^^^^^^ each LINE is converted to lowercase here in the insensitive search
results.push(line);
}
“如何停止重复逻辑?” - 嗯,它们一开始就不完全相同。我认为您的尝试并不完全是您最初想要的(尽管很高兴得到纠正)。
关于string - 如何传递修改后的字符串参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51166835/