Caballero
Caballero

Reputation: 12101

How can I pattern match on a vector of string slices and extract values?

I have a string input that needs to be split into values and pattern matched, so I'm looking for the best way to do that.

This is what I've got so far.

fn main() {
    let s: &str = "A 1 2 3 4";

    let v: Vec<&str> = s.split(" ").collect();

    match &v[..] {
        [letter, x1, x2, x3] => println!("{:?}", letter), //do something with values
        [letter, x1, x2, x3, x4] => println!("{:?}", letter), //do something with values
        _ => println!("no match"),
    }
}

I have several issues with this approach:

  1. This code produces error error: slice pattern syntax is experimental (see issue #23121) so I'm assuming I have to use nightly for it to work? Do I have to import any additional module for it as well?
  2. Is there a similarly simple approach that wouldn't require nightly?
  3. Is there an elegant way to do further matching to pull integer values? For instance is it possible to convert vector into tuple so that ("A", 1, 2, 3, 4) would match and ("A", 1, 2, "D") wouldn't?

Upvotes: 4

Views: 7944

Answers (1)

Lukas Kalbertodt
Lukas Kalbertodt

Reputation: 88626

  1. This code produces error error: slice pattern syntax is experimental (see issue #23121) so I'm assuming I have to use nightly for it to work? Do I have to import any additional module for it as well?

Before Rust 1.26 you have to use a nightly compiler and add #![feature(slice_patterns)] to your crate root. As of Rust 1.26, your original code works as-is.

  1. Is there a similarly simple approach that wouldn't require nightly?

In your example, you branch depending on length of the resulting vector. So of course you can just match v.len(). Once you know the length of the vector, you can access it with []. To bind those to nice names, you can do it like this:

match v.len() {
    4 => {
        let (letter, x1, x2, x3) = (v[0], v[1], v[2], v[3]);
        // ...
    }
    // ...
}

It's certainly not as nice as the slice pattern, but at least it works on stable Rust before the desired syntax was available.

  1. Is there an elegant way to do further matching to pull integer values? For instance is it possible to convert vector into tuple so that ("A", 1, 2, 3, 4) would match and ("A", 1, 2, "D") wouldn't?

You can't really do type conversions within pattern matching. Converting slices into tuples doesn't work either -- both things are pretty different types. Slices are homogeneous and their length is not known at compile time; tuples can hold variables of different types and their length has to be known at compile time.

Upvotes: 5

Related Questions