9

I would like to take a mutable slice and copy the contents into two new mutable slices. Each slice being one half of the original.

My attempt #1:

let my_list: &mut [u8] = &mut [0, 1, 2, 3, 4, 5];
let list_a: &mut [u8] = my_list[0..3].clone();
let list_b: &mut [u8] = my_list[3..6].clone();
println!("{:?}", my_list);
println!("{:?}", list_a);
println!("{:?}", list_b);

Output:

error: no method named `clone` found for type `[u8]` in the current scope
 --> src/main.rs:3:43
  |
3 |     let list_a: &mut [u8] = my_list[0..3].clone();
  |                                           ^^^^^

error: no method named `clone` found for type `[u8]` in the current scope
 --> src/main.rs:4:43
  |
4 |     let list_b: &mut [u8] = my_list[3..6].clone();
  |                                           ^^^^^

My attempt #2:

let my_list: &mut [u8] = &mut [0, 1, 2, 3, 4, 5];
let list_a: &mut [u8] = my_list[0..3].to_owned();
let list_b: &mut [u8] = my_list[3..6].to_owned();
println!("{:?}", my_list);
println!("{:?}", list_a);
println!("{:?}", list_b);

Output:

error[E0308]: mismatched types
  --> src/main.rs:12:29
   |
12 |     let list_a: &mut [u8] = my_list[0..3].to_owned();
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ expected &mut [u8], found struct `std::vec::Vec`
   |
   = note: expected type `&mut [u8]`
              found type `std::vec::Vec<u8>`
   = help: try with `&mut my_list[0..3].to_owned()`

error[E0308]: mismatched types
  --> src/main.rs:13:29
   |
13 |     let list_b: &mut [u8] = my_list[3..6].to_owned();
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ expected &mut [u8], found struct `std::vec::Vec`
   |
   = note: expected type `&mut [u8]`
              found type `std::vec::Vec<u8>`
   = help: try with `&mut my_list[3..6].to_owned()`

I can use two Vec<u8> and just loop over the input and push cloned values I guess, but I was hoping there was a nicer way to do this:

extern crate rand;

use rand::{thread_rng, Rng};

fn main() {
    let my_list: &mut [u8] = &mut [0; 100];
    thread_rng().fill_bytes(my_list);
    let list_a = &mut Vec::new();
    let list_b = &mut Vec::new();
    for i in 0..my_list.len() {
        if i < my_list.len() / 2 {
            list_a.push(my_list[i].clone());
        } else {
            list_b.push(my_list[i].clone());
        }
    }
    println!("{:?}", list_a.as_slice());
    println!("{:?}", list_b.as_slice());
    println!("{:?}", my_list);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user439299
  • 831
  • 4
  • 12
  • 23

3 Answers3

12

The split_at and split_at_mut methods will give you two slices, which you can then copy or even safely use without copying if borrow checker allows.

let (list_a, list_b) = my_list.split_at_mut(my_list.len()/2)
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Kornel
  • 97,764
  • 37
  • 219
  • 309
8

You can build vectors from slices directly by cloning the elements using multiple methods:

  1. Vec::to_vec
  2. From / Into
  3. ToOwned
fn main() {
    let my_list: &mut [u8] = &mut [0, 1, 2, 3, 4, 5];
    let mut vec1 = my_list[0..2].to_vec();
    let mut vec2: Vec<u8> = my_list[2..4].into();
    let mut vec3 = my_list[2..6].to_owned();

    println!("{:?}", vec1);
    println!("{:?}", vec2);
}

Your original problem was caused because all of these return a Vec but you were attempting to claim that it was a slice, equivalent to:

let thing: &mut [u8] = Vec::new();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
snf
  • 2,857
  • 1
  • 18
  • 20
  • Nice, I didn't realize this function existed. – A.B. Jul 21 '14 at 20:47
  • Nice, definitely the cleanest I've seen so far. Is there any disadvantage to using Vec vs &[] or &mut []? Obviously Vec is easier to work with but it seems like there might be some overhead. – user439299 Jul 21 '14 at 20:54
  • 1
    A slice is just a representation, if you call as_slice(), it will borrow a reference to the vector but not creating a new one. If in doubt, check the lifetime parameters ( http://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_slice ), it has the same lifetime as the vector. – snf Jul 21 '14 at 20:58
  • Would this be different than using slice? I expect changing elements in slice will also change the elements in the original vector as well, but mutating on the new vector won't change the original vector? Sorry if this sounds naive, I am new to Rust – qinsoon Nov 25 '15 at 00:31
3

You could chain two iterators over the slices.

let my_list: &mut [u8] = &mut [0, 1, 2, 3, 4, 5];
let mut slices = my_list[0..3].iter().chain(my_list[3..6].iter());
for e in slices {}

chain will iterate over the first iterator, then the second.

To create new lists:

let my_list: &mut [u8] = &mut [0, 1, 2, 3, 4, 5];
let mut a: Vec<u8> = my_list[0..3].iter().cloned().collect();
let mut b: Vec<u8> = my_list[3..6].iter().cloned().collect();
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
A.B.
  • 15,364
  • 3
  • 61
  • 64
  • Is looping over slices different than looping over my_list? I am trying to end up with two new lists in addition to the original. – user439299 Jul 21 '14 at 19:40
  • If you want new lists, create two vectors. Slices are just a view into some vector. – A.B. Jul 21 '14 at 20:36
  • I get this when I try to chain iter() and slice(): **failed to find an implementation of trait core::iter::FromIterator for &mut [u8]**... EDIT: nvm forgot to add Vec – user439299 Jul 21 '14 at 20:42
  • 1
    Why do you want to avoid Vec? This is what it's there for. Slices are not a container - just a view into some other container. – A.B. Jul 21 '14 at 20:48
  • Was doing this as more of a learning experience. Figured if Vec is able to do something similar on the back end I should be able to do it on the front end. It turned into more of a struggle than I would have liked. – user439299 Jul 21 '14 at 20:59
  • 1
    You can not borrow a mutable reference twice. Slice::clone makes a shallow copy (borrowing the elements as mutable) and that's why you can not make two mutable slices clones. If you create a vector, it makes a deep copy, copying all the elements too (must have the trait Clone). – snf Jul 21 '14 at 21:19