1

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?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Emanuel Lindström
  • 1,607
  • 16
  • 25
  • See also: [How can I unpack (destructure) elements from a vector?](/q/32324645/2189130), [How do I destructure a vector without taking a slice?](/q/29316582/2189130), and [How to destructure a Vec into variables that take ownership?](/q/43657570/2189130) – kmdreko Jan 09 '23 at 00:15

2 Answers2

2

You can use match with following pattern.

[first, middle @ .., last]

to bind the first and last values, and store the rest of them in a single array(middle).

ie,

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.

"first", ["second"], "third"

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")
    };
}
Abdul Niyas P M
  • 18,035
  • 2
  • 25
  • 46
0

Ok, I found a way to destructure arbitrary entries from an array (vec) in rust. It's not perfect. If the index is out of bounds the program will panic.

let [first, second, fifth] = { [my_vec[0], my_vec[1], my_vec[5]] };

I also found that you can do string slices, but as far as I see I can only take ranges, not pick and chose. At least not without it being verbose and complicated.

let [first, second, third]: &[_; 3] = my_vec[..3].try_into().unwrap();
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Emanuel Lindström
  • 1,607
  • 16
  • 25