Boden Garman
Boden Garman

Reputation: 2545

How can I unpack (destructure) elements from a vector?

I am currently doing the following:

let line_parts = line.split_whitespace().take(3).collect::<Vec<&str>>();
let ip = line_parts[0];
let bytes = line_parts[1];
let int_number = line_parts[2];

Is it possible to do something like this?

let [ip, bytes, int_number] = line.split_whitespace().take(3).collect();

I'm noticed various references to vector destructuring on some sites but the official docs don't seem to mention it.

Upvotes: 33

Views: 17639

Answers (3)

zmunk
zmunk

Reputation: 56

You can do this:

let line = "127.0.0.1 1000 3";
let [ip, bytes, int_number]: [&str; 3] = line
    .split_whitespace()
    .take(3)
    .collect::<Vec<_>>()
    .try_into()
    .unwrap();

Upvotes: 0

Ronak Agarwal
Ronak Agarwal

Reputation: 211

You can also use this:

use std::convert::TryFrom;

let v = line.split_whitespace().take(3).collect::<Vec<&str>>();
let [ip, bytes, int_number] = <[&str; 3]>::try_from(v).ok().unwrap();

The return type of <[&str; 3]>::try_from(v) will be the Result type which you can use for error handling or allow it to panic as I did, since we already know that the size is 3.

Upvotes: 11

llogiq
llogiq

Reputation: 14511

It seems what you need is "slice patterns":

fn main() {
    let line = "127.0.0.1 1000 what!?";
    let v = line.split_whitespace().take(3).collect::<Vec<&str>>();

    if let [ip, port, msg] = &v[..] {
         println!("{}:{} says '{}'", ip, port, msg);
    }
}

Playground link

Note the if let instead of plain let. Slice patterns are refutable, so we need to take this into account (you may want to have an else branch, too).

Upvotes: 48

Related Questions