# How can I swap two elements in a 2d vector?

Hello again,

Yet another beginner question, this time about swapping elements in a 2d vector.

Given this 2d-vector

``````let mut m = vec![
vec![1,2,3],
vec![4,5,6],
vec![7,8,9]
];
``````

I can swap the first and last elements by doing

``````let tmp = m[0][0];
m[0][0] = m[2][2];
m[2][2] = tmp;
``````

However, this does not seem to work in this example, where `grid` is a struct field defined as `grid : Vec<Vec<Tile>>`

``````fn swap(&mut self, src_r : usize, src_c : usize, dst_r : usize, dst_c : usize) -> ()
{
let t = self.grid[src_r][src_c];
self.grid[src_r][src_c] = self.grid[dst_r][dst_c];
self.grid[dst_r][dst_c] = t;
}
``````

How can I solve this? Is there some mem::swap function I should use?

First, if `Tile` is a small object, consider making it a `Copy` type (`#[derive(Copy)]`), so it will be easy to work with. Instead of â€ścanâ€™t move out of borrowed contextâ€ť error, the compiler will copy it.

Swap can be used, but thereâ€™s a catch. The borrow checker doesnâ€™t understand that `vec[0]` and `vec[1]` are different! So when you borrow both, it just sees `vec` borrowed twice and complains. The solution to this is

``````let (left, right) = vec.split_at_mut(position);
``````

`split_at_mut` gives you two separate slices pointing into two non-overlapping areas in the same vector or slice.

BTW: thereâ€™s no 2D vector in Rust. What you have is a â€śjagged arrayâ€ť where every row is allowed to have a different dimension. If your grid has a fixed size, then 2D array may work (`[[Tile; width]; height]`). Thereâ€™s imgref crate that gets close to being a 2D vector by adding 2D addressing to a 1D vectors. Itâ€™s designed for images, but would work with other types.

2 Likes

@kornel Thanks! Deriving copy and clone worked.

I will attempt the mem::swap as well, will let you know how it goes

If you donâ€™t want to clone `Tile` but it has a default value, you can also use two `mem::replace` calls:

``````fn swap(&mut self, src_r : usize, src_c : usize, dst_r : usize, dst_c : usize) -> () {
let t = ::std::mem::replace(&mut self.grid[src_r][src_c], Tile::default());
self.grid[src_r][src_c] = ::std::mem::replace(&mut self.grid[dst_r][dst_c], t);
}``````