How to loop over a vector of integers in Rust?

Viewed 1469

I know the code below works:

// method 1
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
  v.iter().map(|x| x * 2).collect()
}

However, I was wondering if it were possible to do it as such:

// method 2
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
  for i in v.iter_mut() {
    // TODO: Fill this up so that each element in the Vec `v` is multiplied by two.
  }
  v
}

So far I've been unable to run the iteration using iter_mut().I'd appreciate it if:

  1. Someone could shed light on how to run the code in this manner.
  2. Shed insight into whether or not there are any performance variations between method 1 and method 2.
4 Answers

You can write to i, like to a C pointer:

fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
  for i in v.iter_mut() {
    *i *= 2;
  }
  v
}

fn main() {
    let mut vec = vec![1,2,3,4,5];
    
    println!("{:?}", vec_loop(vec));
}

As for performance, you can always measure it! Also, collect should allocate a new vector, while the approach with the loop modifies existing memory in-place, so it should be faster on big vectors. To me, v.iter().map(|x| x * 2).collect() looks cleaner, and I'd use that for readability purposes.

You have to use the dereference operator (*):

fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
    for i in v.iter_mut() {
      *i *= 2;
    }
    v
}

You can dereference and mutate mutable references using the deref * operator:

fn vec_loop_1(v: Vec<i32>) -> Vec<i32> {
    v.into_iter().map(|x| x * 2).collect()
}

fn vec_loop_2(mut v: Vec<i32>) -> Vec<i32> {
    for i in v.iter_mut() {
        *i *= 2;
    }
    v
}

fn main() {
    assert_eq!(vec_loop_1(vec![1, 2, 3]), vec![2, 4, 6]);
    assert_eq!(vec_loop_2(vec![1, 2, 3]), vec![2, 4, 6]);
    assert_eq!(vec_loop_1(vec![1, 2, 3]), vec_loop_2(vec![1, 2, 3]));
}

playground


Shed insight into whether or not there are any performance variations between method 1 and method 2.

vec_loop_1 allocates a new Vec and vec_loop_2 does not. The latter will be faster and use less memory.

Just to expand onto the previous answer by pretzelhammer, you can mutate the original vector as well without returning any data.

fn vec_loop_1(v: Vec<i32>) -> Vec<i32> {
    v.iter().map(|x| x * 2).collect()
}

fn vec_loop_2(mut v: Vec<i32>) -> Vec<i32> {
    for i in v.iter_mut() {
        *i *= 2;
    }
    v
}

fn vec_loop_3(v: &mut Vec<i32>) {
    for i in v.iter_mut() {
        *i *= 2;
    }
}

fn main() {
    assert_eq!(vec_loop_1(vec![1, 2, 3]), vec![2, 4, 6]);
    assert_eq!(vec_loop_2(vec![1, 2, 3]), vec![2, 4, 6]);
    assert_eq!(vec_loop_1(vec![1, 2, 3]), vec_loop_2(vec![1, 2, 3]));
    let mut new_vec = vec![1, 2, 3];
    vec_loop_3(&mut new_vec);
    assert_eq!(new_vec, vec![2, 4, 6]);
}

vec_loop_3 will mutate its borrowed data instead of taking in a vector and returning a vector.

Related