# How to delete element when iterating a vec?

For example the following codes will throw exception:index out of bounds: the len is 3 but the index is 3

``````   let mut vecc = vec![1, 2, 3, 4];

for i in 0..vecc.len() {
if vecc[i] == 1 {
vecc.remove(i);
}
}``````

Mutating while iterating is a tough sell in many languages, Rust among them. It's doable, but I would try to find a way not to. There's often a method you can call to avoid an explicit loop, such as `retain` for your example:

``````vecc.retain(|&i| i != 1);
``````

Playground

5 Likes

The following can also work:

``````    let mut vecc = vec![1, 2, 3, 4];
let mut idx = 0 as usize;

while  idx < vecc.len() {
if vecc[idx] == 1 {
vecc.remove(idx);
continue;
}
idx = idx + 1;
}``````
1 Like

It is great!

Note that calling `remove` in a loop is also more inefficient. `Vec::remove` takes linear1 time (it has to shift all the elements to the right of the removed element one to the left in memory); thus calling `.remove` in a loop can take quadratic1 time; whereas `.retain` only takes linear1, 2 time for the whole process (it can use an implementation that – as an intermediate state – leaves some “slots” of memory empty during the iteration, with the effect of only having to move each item of the vec at most once).

1 linear/quadratic with respect to the length of the vector
2 assuming that the closure given to `.retain` only needs constant time

5 Likes

To translate this into code, `Vec::retain()` works similarly¹ to this:

``````    let mut vecc = vec![1, 2, 3, 4];

let mut idx_wr = 0usize;
for idx_rd in 0..vecc.len() {
if ! (vecc[idx_rd] == 1) {
vecc.swap(idx_wr, idx_rd);
idx_wr += 1;
}
}

vecc.truncate(idx_wr);
``````

¹ I haven't looked at the actual code for `retain`; it probably uses `unsafe` to perform a move instead of the `swap` call I used.

2 Likes

yup, that’s exactly what it does.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.