我正在尝试使用该retain(...)方法从向量中过滤掉值.目前,我的代码到目前为止
let results = get_data(); // Returns Result<Vec<MyData>, Box<Error>>
match results {
Ok(mut my_data) => {
// Make sure that `name` is not None
myData.retain(|ref d| d.name.is_some());
// Only keep data if 'name' is in this list
let names = ["Alice", "Bob", "Claire"];
my_data.retain(|ref d| names.contains(d.name.unwrap().as_str()));
},
Err(_) => {}
}
Run Code Online (Sandbox Code Playgroud)
但是,这会产生错误
|
| my_data.retain(|ref d| names.contains(d.name.unwrap().as_str()));
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected &str, found str
|
= note: expected type `&&str`
found type `&str`
Run Code Online (Sandbox Code Playgroud)
看起来编译器在这里告诉我两个不同的东西,但在这两种情况下它似乎都想要一个额外的参考.但是,当我尝试将相关行更改&names.contains(d.name.unwrap().as_str())为时,编译器会抛出以下错误.
|
| my_data.retain(|ref d| names.contains(&d.name.unwrap().as_str()));
| ^ cannot move out of borrowed content
Run Code Online (Sandbox Code Playgroud)
如何检查向量中是否包含借用的String(我认为这是什么类型name.unwrap())names?
这是你的问题的MCVE(你的原始代码有其他无关的问题,这里忽略了):
struct MyData {
name: Option<String>,
}
fn main() {
let mut my_data: Vec<MyData> = vec![];
// Only keep data if 'name' is in this list
let names = ["Alice", "Bob", "Claire"];
my_data.retain(|ref d| names.contains(d.name.unwrap().as_str()));
}
Run Code Online (Sandbox Code Playgroud)
error[E0308]: mismatched types
--> src/main.rs:10:43
|
10 | my_data.retain(|ref d| names.contains(d.name.unwrap().as_str()));
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected &str, found str
|
= note: expected type `&&str`
found type `&str`
Run Code Online (Sandbox Code Playgroud)
如错误消息所述,slice::contains需要引用切片中包含的值类型:
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq<T>,
Run Code Online (Sandbox Code Playgroud)
由于切片包含字符串文字(类型&'static str),因此需要&&str进行比较.我们将参考该as_str方法的结果:
my_data.retain(|ref d| names.contains(&d.name.unwrap().as_str()));
// ^-- added
Run Code Online (Sandbox Code Playgroud)
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:44
|
10 | my_data.retain(|ref d| names.contains(&d.name.unwrap().as_str()));
| ^ cannot move out of borrowed content
Run Code Online (Sandbox Code Playgroud)
Stack Overflow上的其他地方已经彻底解释了这个错误:
TL; DR - 您不拥有d,因此您无法解包d.name,消耗过程中的值.修复是使用Option::as_ref:
my_data.retain(|ref d| names.contains(&d.name.as_ref().unwrap().as_str()));
// ^^^^^^^^^-- added
Run Code Online (Sandbox Code Playgroud)
然而,需要unwrap是丑陋的,理想的是避免.您可以将两个retain调用合并为一个,并使用Option::map_or以下命令跳过展开:
my_data.retain(|d| {
d.name.as_ref().map_or(false, |name| {
let name = name.as_str();
names.contains(&name)
})
});
Run Code Online (Sandbox Code Playgroud)
这消除了潜在的恐慌并提高了代码的效率.
| 归档时间: |
|
| 查看次数: |
156 次 |
| 最近记录: |