Vec::remove¶
Level: reference · for working programmers
One line: Take the element at index out, shifting everything after it left.
Stable since 1.0.0.
O(n − index), because order is preserved: every element after the hole moves one place. That is the whole trade against swap_remove, which is O(1) and does not preserve order.
Panics if index >= len(). There is no stable non-panicking sibling (try_remove is unstable), so the guard is yours to write — or use if index < v.len().
Removing several elements by index is a trap: the later indices move as soon as the first one goes. Iterate back to front, or — better — use retain, which is a single pass and cannot get the arithmetic wrong.
remove(0) in a loop is quadratic. If you are consuming from the front, drain, VecDeque or reversing once are all better answers.
Example¶
vec_remove.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let mut v = vec!["a", "b", "c", "d"];
println!("removed {:?}, left {v:?}", v.remove(1));
// Order is preserved, which is what makes it O(n): everything after the
// hole shifts left by one.
let mut v: Vec<u8> = (0..8).collect();
v.remove(0);
println!("remove(0) keeps order: {v:?}");
// Removing several by index means the later indices move under you.
// Going back to front avoids that; retain avoids the whole problem.
let mut v = vec![10, 11, 12, 13, 14];
for i in [3, 1] { v.remove(i); } // descending order on purpose
println!("removed indices 1 and 3: {v:?}");
let mut v = vec![10, 11, 12, 13, 14];
let mut i = 0;
v.retain(|_| { let keep = i != 1 && i != 3; i += 1; keep });
println!("the same thing with retain: {v:?}");
// Out of bounds panics; there is a non-panicking sibling only in nightly,
// so the guard is yours to write.
let mut v = vec![1, 2, 3];
let idx = 7;
if idx < v.len() { v.remove(idx); } else { println!("index {idx} is past len {}", v.len()); }
let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let caught = std::panic::catch_unwind(|| { let mut v = vec![1]; v.remove(3); });
std::panic::set_hook(hook);
println!("remove(3) from a len-1 vec panicked: {}", caught.is_err());
}
Verified output of vec_remove.rs — regenerated by tools/run_examples.py, never hand-typed.
removed "b", left ["a", "c", "d"]
remove(0) keeps order: [1, 2, 3, 4, 5, 6, 7]
removed indices 1 and 3: [10, 12, 14]
the same thing with retain: [10, 12, 14]
index 7 is past len 3
remove(3) from a len-1 vec panicked: true
See also¶
Vec::swap_remove— O(1), at the cost of the orderVec::retain— removing many in one passVec::drain— removing a whole range and keeping itVec::insert— the inverse, with the same cost