string - 如何传递修改后的字符串参数?

标签 string rust borrow-checker

我正在使用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)
}

这是running in the Playground

编辑:

我意识到我从未真正给过你替代方案。这是我可能会做的:

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)
}

Here it is on the playground

尽管如此,您仍然需要复制逻辑...因为您需要将小写查询与小写行相匹配...这在书中的示例中进行了演示:

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/

相关文章:

rust - 如何注释此 Rust/Calloop 回调代码的生命周期?

rust - 如何使用(不安全的)别名?

multithreading - 如何将 JoinHandle 存储在与自身运行的线程的结构中?

c# - 使用正则表达式搜索字符串

php - 检查字符串以查找内部变量(PHP)

rust - 如何查询主机三元组的 rustc?

rust - 重命名匹配中的枚举字段 (rust)

optimization - 如何加快我的近似自然对数函数?

algorithm - 递归字符串置换函数的复杂性

java - 如何使这段代码更简洁?