我想过滤掉Option
向量中的一些项目,我想在不创建新向量的情况下这样做,因为它可以通过map
和{{的组合来完成1}}。我不想使用collect
,因为这已被弃用。
我找到了以下解决方案:
Vec::map_in_place
虽然它工作正常,但每个元素都会生成2个副本,无论元素是否被修改。
是否有更惯用的解决方案还需要更少的复制?
答案 0 :(得分:2)
冒着大规模过度拟合的具体例子;以下内容也适用:
fn main() {
let mut v = vec![Some("10".to_owned()), Some("5".to_owned()),
None, Some("20".to_owned())];
for i in v.iter_mut() {
if i.as_ref().map_or(false, |f| *f == "20") {
i.take();
}
}
println!("v = {:?}", v);
}
也许你过分简化了你的例子,但对于给定的程序,如果只能用一个副本完成,并且只在需要更改时。主要的想法是,您首先要检查是否需要更改(即i
是Some("20")
),然后您只需进行更改。借用借来的小舞似乎是必要的,但解决办法如下:
use std::mem;
fn main() {
let mut v = vec![Some("10".to_owned()), Some("5".to_owned()),
None, Some("20".to_owned())];
for i in v.iter_mut() {
// Borrowchk-dance: make sure this borrow of i ends before we try to mutate
let is_a_twenty = match i {
&mut Some(ref f) if *f == "20" => true,
_ => false,
};
// Now that we're free to borrow i mutably, go ahead and do so
if is_a_twenty {
mem::replace(i, None);
}
}
println!("v = {:?}", v);
}
答案 1 :(得分:0)
这里有两种更直接的方法,一种使用 for 循环,一种使用迭代器:
fn g(number_strings: &mut Vec<Option<String>>, target: &str) {
for some_string in number_strings.iter_mut() {
if let Some(ref string) = some_string {
if string == target {
*some_string = None;
}
}
}
}
fn h(number_strings: &mut Vec<Option<String>>, target: &str) {
number_strings
.iter_mut()
.filter(|s| s.is_some() && s.as_ref().unwrap() == target)
.for_each(|s| *s = None);
}
fn main() {
let mut v = vec![
Some("10".to_owned()),
Some("5".to_owned()),
None,
Some("20".to_owned()),
Some("10".to_owned()),
Some("20".to_owned()),
];
println!("{:?}", v);
g(&mut v, "10");
println!("{:?}", v);
h(&mut v, "20");
println!("{:?}", v);
}
输出:
[Some("10"), Some("5"), None, Some("20"), Some("10"), Some("20")]
[None, Some("5"), None, Some("20"), None, Some("20")]
[None, Some("5"), None, None, None, None]