# 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;
m = m;
m = 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?

Thanks in advance 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` and `vec` 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);
}``````