0

I have a vector of a vector and need to concatenate the second one to the first (it's ok if the second one is dropped), i.e.

f([[1,2,3], [4,5,6]]) => [[1,2,3,4,5,6], []]

or

f([[1,2,3], [4,5,6]]) => [[1,2,3,4,5,6], [4,5,6]]

Both are okay.

My initial solution is:

fn problem() {
    let mut items = Vec::new();
    items.push(vec![1,2,3]);
    items.push(vec![4,5,6]);
    items[0].append(&mut items[1]);
}

But it has a compile time error due to 2 mutable borrows:

   |     items[0].append(&mut items[1]);
   |     -----    ------      ^^^^^ second mutable borrow occurs here
   |     |        |
   |     |        first borrow later used by call
   |     first mutable borrow occurs here

I could solve it with Box / Option, but I wonder whether there are better ways to solve this?


My solution with Box:

fn solution_with_box() {
    let mut items = Vec::new();
    items.push(Box::new(vec![1,2,3]));
    items.push(Box::new(vec![4,5,6]));
    let mut second = items[1].clone();
    items[0].as_mut().append(second.as_mut());
}

My solution with Option:

fn solution_with_option() {
    let mut items = vec::new();
    items.push(some(vec![1,2,3]));
    items.push(some(vec![4,5,6]));
    let mut second = items[1].take();
    items[0].as_mut().unwrap().append(second.as_mut().unwrap());
}
pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
Pahlevi Fikri Auliya
  • 4,157
  • 8
  • 35
  • 71
  • Does this answer your question? [How can I swap in a new value for a field in a mutable reference to a structure?](https://stackoverflow.com/questions/27098694/how-can-i-swap-in-a-new-value-for-a-field-in-a-mutable-reference-to-a-structure) – trent Oct 11 '20 at 13:10
  • `Vec` implements `Default`, so you can use `mem::take` as Shepmaster's answer suggests. [Here's what that might look like.](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1a44dfc8d725109c2d6e7ba5f24f7cd4) – trent Oct 11 '20 at 13:11

4 Answers4

1

You can clone the data of items[1] as follows:

fn main() {
    let mut items = Vec::new();
    items.push(vec![1,2,3]);
    items.push(vec![4,5,6]);
    let mut a: Vec<i32> = items[1].clone();
    &items[0].append(&mut a);
}

If you don't want to clone the data, you can use mem::take as suggested by @trentcl

fn main() {
    let mut items = Vec::new();
    items.push(vec![1,2,3]);
    items.push(vec![4,5,6]);
    let second = std::mem::take(&mut items[1]);
    items[0].extend(second);
    println!("{:?}", items);
}
edkeveked
  • 17,989
  • 10
  • 55
  • 93
0

This is not fastest way of doing it but it solves your problem.

fn problem() {
    let mut items = Vec::new();
    items.push(vec![1,2,3]);
    items.push(vec![4,5,6]);

    //we can not have two mutable references in the same scope
    // items[0].append(&mut items[1]);

    // instead you can flatten vector
    let first = items.into_iter().flatten().collect(); // we consume items so its no longer available
    let items = vec![first, vec![]];

    println!("{:?}", items); // [[1,2,3,4,5,6], []]
}
109149
  • 1,223
  • 1
  • 8
  • 24
0

You can use split_at_mut on a slice or vector to get mutable references to non-overlapping parts that can't interfere with each other, so that you can mutate the first inner vector and the second inner vector at the same time.

let mut items = Vec::new();
items.push(vec![1,2,3]);
items.push(vec![4,5,6]);

let (contains_first, contains_second) = items.split_at_mut(1);
contains_first[0].append(&mut contains_second[0]);

dbg!(items);

Rust Playground link

No copying or cloning occurs. Note that contains_second[0] corresponds to items[1] because the second slice split_at_mut returns starts indexing at wherever the split point is (here, 1).

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
0

you can solve the problem in two steps:
append the empty vector at the end
remove items[1] and append its elements to items[0]

fn problem() {
    let mut items = Vec::new();
    items.push(vec![1,2,3]);
    items.push(vec![4,5,6]);
    items.push(vec![0;0]);
    let v = items.remove(1);
    items[0].extend(v);
}
Kaplan
  • 2,572
  • 13
  • 14