【发布时间】:2014-10-07 18:45:30
【问题描述】:
有没有一种简单的方法可以从Vec<T> 中删除元素?
有一个名为remove() 的方法,它需要一个index: usize,但我什至看不到index_of() 方法。
我正在寻找一些(希望)简单且 O(n) 的东西。
【问题讨论】:
标签: rust
有没有一种简单的方法可以从Vec<T> 中删除元素?
有一个名为remove() 的方法,它需要一个index: usize,但我什至看不到index_of() 方法。
我正在寻找一些(希望)简单且 O(n) 的东西。
【问题讨论】:
标签: rust
这是我迄今为止提出的(这也让借阅检查员很高兴):
let index = xs.iter().position(|x| *x == some_x).unwrap();
xs.remove(index);
我仍在等待找到更好的方法来做到这一点,因为这很丑。
注意:我的代码假定该元素确实存在(因此是 .unwrap())。
【讨论】:
您可以使用retain method,但它会删除该值的每个实例:
fn main() {
let mut xs = vec![1, 2, 3];
let some_x = 2;
xs.retain(|&x| x != some_x);
println!("{:?}", xs); // prints [1, 3]
}
【讨论】:
您的问题没有明确说明:您是要返回 所有 项等于您的针还是只返回 一个?如果有,第一个还是最后一个?如果没有一个元素等于你的针呢?可以用快速的swap_remove 删除它还是需要较慢的remove?为了迫使程序员思考这些问题,没有简单的方法可以“删除一个项目”(有关详细信息,请参阅this discussion)。
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
与第一个元素类似,但将 position 替换为 rposition。
needle
vec.retain(|x| *x != needle);
swap_remove
请记住,remove 的运行时间为 O(n),因为索引之后的所有元素都需要移动。 Vec::swap_remove 的运行时间为 O(1),因为它将要删除的元素与最后一个元素交换。如果在您的情况下元素的顺序并不重要,请使用swap_remove 而不是remove!
【讨论】:
迭代器有一个position() 方法,它返回与谓词匹配的第一个元素的索引。相关问题:Is there an equivalent of JavaScript's indexOf for Rust arrays?
还有一个代码示例:
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 借用为不可变的,因为它也被借用为可变的”
drain_filter() 是最新答案中的新成员吗?
好像和凯的回答差不多:
#![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
【讨论】:
如果您的数据已排序,请使用二进制搜索来删除O(log n),这对于大型输入可能会快得多。
match values.binary_search(value) {
Ok(removal_index) => values.remove(removal_index),
Err(_) => {} // value not contained.
}
【讨论】: