[SOLVED] How do I modify a collection without consuming it?

Issue

I want to modify a collection in place before returning it:

fn main() {
    println!("{:?}", compute()); // should print [[2, 1, 0], [5, 4, 3]]
}

// u8 is just a placeholder, so impl Copy is considered cheating :)
fn compute() -> Vec<Vec<u8>> {
    let a = vec![0, 1, 2];
    let b = vec![3, 4, 5];

    let mut result = Vec::new();
    result.push(a);
    result.push(b);

    // avoids allocations from:
    //
    // result.iter()
    //     .map(|r| {
    //         r.reverse()
    //         r
    //     })
    //     .collect::<Vec<_>>()
    result.into_iter().for_each(|mut r| r.reverse());

    // errors out: the collection was consumed the line above
    result
}

A collection was already allocated with Vec::new(), so allocating a second collection here seems like a waste. I am assuming that’s what .collect() does.

  1. How do I avoid the allocation in excess?
  2. Is there any easy way to know how many allocations are happening? In golang it was as easy as go test -bench=., but I can’t find anything similar when it comes to Rust.

Link to playground

Solution

You need to use a &mut to each of the inside vectors, for that you can just use iter_mut which uses &mut Self instead of Self for the outer vector.

// u8 is just a placeholder, so impl Copy is considered cheating :)
fn compute() -> Vec<Vec<u8>> {
    let a = vec![0, 1, 2];
    let b = vec![3, 4, 5];

    let mut result = Vec::new();
    result.push(a);
    result.push(b);

    result.iter_mut().for_each(|r| r.reverse());

    result
}

Playground

Answered By – Netwave

Answer Checked By – Senaida (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *