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

String 如何传递修改后的字符串参数?,string,rust,borrow-checker,String,Rust,Borrow Checker,我在上,实现了不区分大小写的行搜索。对我来说,两次实现相同的逻辑是没有意义的,所以我想,如果我调用区分大小写的搜索函数,并将参数转换为小写,这可能会起作用。事实并非如此 这是我的非工作代码: fn main() { let a = search("Waldo", "where in\nthe world\nis Waldo?"); let b = search("waldo", "where in\nthe world\nis Waldo?"); let c = sear

我在上,实现了不区分大小写的行搜索。对我来说,两次实现相同的逻辑是没有意义的,所以我想,如果我调用区分大小写的搜索函数,并将参数转换为小写,这可能会起作用。事实并非如此

这是我的非工作代码:

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)
}
fn main(){
让a=搜索(“瓦尔多”,“世界上哪里是瓦尔多?”);
让b=搜索(“瓦尔多”,“世界上哪里是瓦尔多?”);
让c=search\u case\u不区分大小写(“waldo”,“where in\n world\nis waldo?”);
println!(“{:?}”,a);
println!(“{:?}”,b);
println!(“{:?}”,c);
}
pub fn search Vec(查询:&str,内容:&a str)->Vec src/main.rs:25:28
|
25 |让contents2:&str=&contents.to_小写();
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^临时值的有效期不够长
...
28 | }
|-临时价值仅在此之前有效
|
注意:借用值必须在生命周期“a”内有效,如函数体23:1所定义。。。
-->src/main.rs:23:1
|

23 | pub fn search _case_insensitive Vec您对变量
内容2的生存期引入了一个不可能的约束;通过编写
&'a
您试图为它指定与
内容
参数相同的生存期,但它是在
搜索范围内创建和销毁的,不区分大小写
,因此它的生存期由
内容
延长

为了使
contents2
search\u case\u insensitive
的主体寿命长,您需要将其作为
字符串返回,并分配给其外部的某个变量,或者通过引用将其传递给
search\u case\u insensitive
,只要它在其他地方已经作为
字符串存在

引用:

重要的是要理解生命周期注释是 描述性,而非规定性。这意味着引用的长度是 valid由代码决定,而不是由注释决定

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

但是你仍然需要复制逻辑。。。因为您需要将小写查询与小写行匹配。。。这在本书中的示例中得到了演示:

if line.to_lowercase().contains(&query) {
//      ^^^^^^^^^^^^^^ each LINE is converted to lowercase here in the insensitive search
    results.push(line);
}

“我怎样才能停止重复逻辑?”-首先,它们并不完全相同。我认为你的尝试并不是你最初想要的(很高兴被纠正)。

嗨!你能解释一下你不明白错误信息的哪一部分吗?有什么让你困惑的?谢谢@卢卡斯·卡尔伯托德不是我不理解这个错误。显然,to_lowercase()返回一个新字符串,因为带有翻转大小写的unicode字符串可能与原始字符串的长度不同。此新字符串必须在函数末尾释放。但是,返回值使用了这个新字符串的一个片段,这就是导致错误的原因。我不明白的是如何修复它。为什么要为
contents2
设置str
?@ljedrz我甚至有一个contents2,我或多或少地随机尝试一些东西,希望让错误消失。添加生存期参数就是其中之一。删除它并不能真正改变错误。仅将其更改为“b”会更改错误。但我需要做的是找到一种方法,使字符串比函数更长寿(我不知道强制借用)或重构,所以这不再是一个问题,但我有点担心lost@Shepmaster我对问题进行了编辑,添加了最少的完整代码。您可以验证它是否会产生相同的错误。如果将函数的返回类型替换为Vec,并将String::from(line)推送到向量中(而不仅仅是line),那么它也会按照预期进行编译和工作。我想这是我一直在寻找的解决方案,尽管也许有更好的方法。在这个例子中,有人可能会认为Simon Whitehead的功能不一样,两个函数都应该有一个循环,但我希望有一个类似的银弹。也许我太乐观了,但这个问题给出了一个完全不同的答案;我看不出它是如何解决OP问题的。@MatthieuM。我查看了书中的示例——这本书实际上将查询小写,因此OP的方向是错误的。他们引入了一个本书中没有的bug,因为他们做了一些完全不同的事情。我没有帮助他们纠正错误,而是试图为他们指出正确的方向,因为如果正确地遵循示例,他们所做的事情不是问题。不管怎样,我认为“逻辑重复数据消除”都不是一个可以实现的目标,因为逻辑的两条核心线需要不同。这就是我想在最后指出的。我已经添加了一个在这种情况下我可能会做的例子。。。但它偏离了你在书中遵循的例子。我的答案的上半部分是基于你们在阅读这本书时犯了什么错误。我知道函数的行为和这本书不同,返回的字符串都是小写的。我对重写grep或完全复制书中的功能并不感兴趣。但我经常编写代码,其中两个具有相同签名的函数中的一个在简短的前奏后调用另一个函数,我认为其他函数在返回字符串引用时可能会遇到类似的问题。我希望得到的答案是类似于“将两个函数的返回值都更改为Vec”之类的东西,或者是我无法得到的更好的东西imagine@Kaan我只是试着让它尽可能接近原始材料。尽管老实说我认为我的解决方案是可以接受的,但我还是会在这里到处使用
String
实例,并将其重构为referec
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);
}