我从Rust编程书中有一个搜索函数,可以搜索与模式匹配的行(查询)。
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut matching_lines: Vec<&str> = Vec::new();
for line in contents.lines() {
if line.contains(query) {
matching_lines.push(line);
}
}
matching_lines
}
在书中,它几乎重写了完全相同的代码来搜索相同的东西但忽略了大写字母,我想通过调用带小写参数的函数来重用相同的代码会更有效率。
pub fn insensitive_search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase().as_str();
let contents_lower = contents.to_lowercase().as_str();
search(query, contents_lower)
}
这将产生以下错误
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:25:17
|
25 | let query = query.to_lowercase().as_str();
| ^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
26 | let contents_lower = contents.to_lowercase().as_str();
27 | search(query, contents_lower)
| ----- borrow later used here
|
我知道这会导致错误,因为to_lowercase
函数获得所有权,我不能从函数返回它,因为它将在函数返回后被清除,这意味着它是无效数据。
我怎样才能重写它使它有效呢?在这里使用String
是否更好?
2条答案
按热度按时间mwg9r5ms1#
我知道这会导致错误,因为to_lowercase函数取得了所有权
它不会这样做,但它确实创建了源代码的副本,以便将其小写。
我怎样重写它才能使它有效?
你不能,因为数据属于当前函数,返回引用向量的唯一方法是如果父函数传入一个可变缓冲区,你可以在其中写入小写数据,然后你可以对 * 那个 * 进行切片,但这对于需要来说是一个巨大的复杂性。
在本例中使用String是否更好?
是的,因为这是
lowercase()
返回的值。在其他情况下,您可以使用
Cow
来避免为新的所有权“付费”,但在这里,这会增加相当多的复杂性,并且(取决于字符串的长度以及已经小写与需要小写的比率)您甚至可能无法补偿条件检查:对于每一个输入字符串,你需要检查它是否已经是小写的,如果是,你可以返回原始字符串的Cow::Borrowed
,否则你返回小写字符串的Cow::Owned
。yws3nbqq2#
如果只使用ASCII字符串,则以下解决方案有效:
字符串将在适当的位置更改为它们的小写等效项。