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);
}
}
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);
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;
}
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
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.
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.