Is it possible to iterate over a vector, fetch its elements, and append to the end?

I want to iterate over a vector of integers, add 1 to each element then append the result to the end of the vector.

What I have tried:

fn main() {
    let mut v = vec![1, 2, 3, 4];
    for i in &mut v {
        v.push(*i + 1);
    }
}
fn main() {
    let mut v = vec![1, 2, 3, 4];
    for i in v.iter_mut() {
        v.push(*i + 1);
    }
}

All of these tries are violates the borrow checker of Rust.

It is ok to use the index as a cursor to fetch each element during iteration:

fn main() {
    let mut v = vec![1, 2, 3, 4];
    for i in 0..v.len() {
        v.push(v[i] + 1);
    }
}

But I feel that this is not very concise. I wonder if there is some "iterator" way to do this.

You cannot use an iterator here because calling push might reallocate, moving where the vector's data is stored. This would break the iterator, since the iterator is fixed to a specific location in memory.

You might like this article, which is about a similar situation. In that other situation, it is possible to use an iterator, but it is not in your case.

1 Like

Hi,

What about making a new vector and then moving the values?

fn main() {
    let mut v = vec![1, 2, 3, 4];
    let mut v1 = Vec::new();

    for i in v.iter_mut() {
        v1.push(*i + 1);
    }

    v.append(&mut v1);
}

Regards,
Alberto

There could be something like Vec::<T>::split_at_mut_vec(&mut self, i: usize) -> (&[T], VecEnd<T>).

It would be like split_at_mut, but the last part would be a wrapper for the second slice, with all the Vec's methods and traits, except it would panic or Err when moving is needed by the allocator. (this is not a problem if you pre-allocate the Vec) It cannot break the slice reference, and you can use the Vec again when VecEnd is dropped.

fn main() {
    let mut before = vec![ 1, 2, 3, 4 ];
    let map: Vec<_> = before.iter()
        .map(|x| x + 1).collect();
    let after: Vec<_> = before.into_iter()
        .chain(map).collect();
    // println!("{:?}", after);
    // out: [1, 2, 3, 4, 2, 3, 4, 5]
}

is another option, if you really want to use iterators.

You could do it in two passes:

let len = v.len();
v.extend_from_within(..); // clone everything
for x in &mut v[len..] {
    *x += 1; // modify the new ones
}
3 Likes

Another way:

let mut v = vec![1,2,3];
let l = v.len();
v.resize(l*2, 0); // useless init with zeros
let (s1, s2) = v.split_at_mut(l); // useless bound check (l <= l*2)
s1.iter().zip(s2.iter_mut()).for_each(|(a, b)| *b = a + 1); // too much iteration overhead because we know s1.len() == s2.len()

It can be optimized (see comments) but it would be unsafe and "not very concise"...

It works but looks redundant. :grinning:

Still a good way.

You give a sophisticated solution to this problem, very interesting.

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.