Search code examples
rustvectordestructuring

How to destructure n items from a vec into variables?


In JavaScript, I can destructure an array in the following way:

const [first, second, ...rest] = myArray

Is there a similar way to achieve this in rust?

If I only want one element, it's easy. I can do:

let first = my_vec[0];

or if I make an array from a string and only want to split i once, in to two parts I can do that and get a tuple with this (if I only need to split the array in to two parts):

let (first, second) = my_string.split_once("\n").unwrap();

But what about the more general destructuring pattern where I can ignore parts of the array and have a few variables defined and ready to go?

I'm expecting it to look something like this:

let [first, second, ...] = my_vec;

or

let [first, ..middle, second_last, last] = my_vec;

P.S.: forget about the unwrap-part. I know I should handle the error, but that's not the point here.

I tried using a match expression, which didn't work. It expects the array to be of length 2.

let [first, second] = match my_vec[..] {
    [first, second] => [first, second],
    v => v,
};

I complains about v and says: `match` arms have incompatible types expected array `[&str; 2]`, found slice `[&str].

That makes sense, so is there a way to achieve this?


Solution

  • You can use match statement with [first, middle @ .., last] as pattern. This will bind the first and last values, and store the rest of them in a single array(middle).

    fn main() {
        let my_vec = vec![1, 2, 3, 4, 5];
        match my_vec.as_slice() {
            [first, middle @ .., last] => {
                println!("{:?}, {:?}, {:?}", first, middle, last)
            },
            _ => {
    
            }
        }
    }
    

    This will result in following output.

    1, [2, 3, 4], 5
    

    You can also use if let syntax:

    fn main() {
        let my_vec = vec!["first", "second"];
        if let [first, middle @ .., last] = my_vec.as_slice() {
            println!("{:?} {:?} {:?}", first, middle, last);
        } else {
            panic!("The slice is either empty or contains only single element")
        };
    }