有没有一种简单的方法可以从 Vec<T>
中删除元素?
有一个名为 remove()
的方法,它需要一个 index: usize
,但我甚至看不到一个 index_of()
方法。
我正在寻找一些(希望)简单的且 O(n) 的东西。
这是我目前想出来的(也让借用检查器满意):
let index = xs.iter().position(|x| *x == some_x).unwrap();
xs.remove(index);
我仍在等待找到更好的方法来做这件事,因为它很丑陋。
注意:我的代码假设该元素存在(因此使用了.unwrap()
)。
retain
方法,但它会删除每个值的所有实例:fn main() {
let mut xs = vec![1, 2, 3];
let some_x = 2;
xs.retain(|&x| x != some_x);
println!("{:?}", xs); // prints [1, 3]
}
你的问题没有明确说明:你是想返回所有等于needle的项目还是只返回一个? 如果是一个,是第一个还是最后一个?如果没有单个元素等于你的needle会怎样?能否使用快速的swap_remove
删除它,还是需要使用较慢的remove
?为了强迫程序员思考这些问题,没有简单的方法可以“删除一个项目”(有关更多信息,请参见此讨论)。
needle
的元素// Panic if no such element is found
vec.remove(vec.iter().position(|x| *x == needle).expect("needle not found"));
// Ignore if no such element is found
if let Some(pos) = vec.iter().position(|x| *x == needle) {
vec.remove(pos);
}
当然,你可以按照自己的意愿处理None
情况(恐慌和忽略不是唯一的可能性)。
needle
的最后一个元素与第一个元素相似,但用rposition
替换position
。
needle
的元素vec.retain(|x| *x != needle);
swap_remove
请记住,remove
的运行时间复杂度为O(n),因为需要对索引后面的所有元素进行移动。而Vec::swap_remove
的运行时间复杂度为O(1),因为它将要删除的元素与最后一个元素交换位置。如果在您的情况下元素的顺序不重要,请使用swap_remove
而不是remove
!
迭代器有一个position()
方法,可返回第一个匹配断言的元素的索引。相关问题:是否有 Rust 数组等价于 JavaScript 的 indexOf
方法?
代码示例:
fn main() {
let mut vec = vec![1, 2, 3, 4];
println!("Before: {:?}", vec);
let removed = vec.iter()
.position(|&n| n > 2)
.map(|e| vec.remove(e))
.is_some();
println!("Did we remove anything? {}", removed);
println!("After: {:?}", vec);
}
xs.remove(xs.iter().position(|x| *x == some_x).unwrap());
-- "无法将 xs
借为不可变的,因为它同时也被作为可变的借用了"。 - Kai Sellgrendrain_filter()
方法是否是最新的?
看起来与Kai的答案相似:
#![feature(drain_filter)]
let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
assert_eq!(numbers, vec![1, 3, 5, 9, 11, 13, 15]);
https://doc.rust-lang.org/std/vec/struct.Vec.html#method.drain_filter
extract_if()
。否则,请使用retain()
。另外,为什么要使用.collect::<Vec<_>>()
? - undefinedO(log n)
的删除操作,这对于大输入数据能够更快地完成。match values.binary_search(value) {
Ok(removal_index) => values.remove(removal_index),
Err(_) => {} // value not contained.
}
pub trait RemoveElem<T> {
fn remove_elem<F>(&mut self, predicate: F) -> Option<T>
where
F: Fn(&T) -> bool;
}
impl<T> RemoveElem<T> for Vec<T> {
fn remove_elem<F>(&mut self, predicate: F) -> Option<T>
where
F: Fn(&T) -> bool,
{
self.iter()
.position(predicate)
.map(|index| self.remove(index))
}
}
let mut a1 = vec![1, 2, 1];
a1.remove_elem(|e| e == &1);
dbg!(&a1); // ouput: [ 2, 1 ]