如何解构 &str 的向量?

How can I destructure a vector of &str?

我的情况:

let mut str_vect = Vec::new();
str_vect.push("a");
str_vect.push("b");
str_vect.push("c");
let [a, bc @ ..] = str_vect[..];
println!("{:?} {:?}", a, bc);

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8e4c47b024e0c871676626069ec07d52

我收到这个错误:

the size for values of type [&str] cannot be known at compilation time

这是为什么?我能以某种方式解构 &strVec 吗?

只需添加一个&v[..]是夏令时([T]不是 &[T])。这很好,只要我们只访问单个元素,但对于生成切片的剩余模式 (..),它们也必须生成 [T],并且未调整大小。另一方面,如果你匹配 &[T],其余模式也会给出 &[T](另一种可能性是使用 ref - ref bc @ ..,但我不建议这样做) .

let [a, bc @ ..] = &str_vect[..];

Playground.

然而,这失败了:

error[E0005]: refutable pattern in local binding: `&[]` not covered
 --> src/main.rs:6:8
  |
6 |    let [a, bc @ ..] = &str_vect[..];
  |        ^^^^^^^^^^^^ pattern `&[]` not covered
  |
  = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
  = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
  = note: the matched value is of type `&[&str]`
help: you might want to use `if let` to ignore the variant that isn't matched
  |
6 |    let (a, bc) = if let [a, bc @ ..] = &str_vect[..] { (a, bc) } else { todo!() };
  |    ++++++++++++++++                                  ++++++++++++++++++++++++++++

那是因为除了 [..] 之外的任何切片模式都是 refutable - 也就是说,可能会失败。如果 str_vect(理论上)有零个元素怎么办?在那种情况下我们不能绑定第一个元素!您需要 if letmatch 来处理这种情况。

另一种解决方案,绝对不是解构,但在我看来更容易阅读,因为名称表达了意图,将依赖于split_first()

    let (a, bc) = str_vect.split_first().unwrap();

当然,应该考虑一些适当的错误处理而不是解包。

是的,另一个答案要好得多,因为它详细解释了所报告错误的来源(我只是赞成它;^)。

另一种选择是使用迭代器:

fn main() {
   let mut str_vect = Vec::new();
   str_vect.push("a");
   str_vect.push("b");
   str_vect.push("c");
   let (a, bc) = {
        let mut it = str_vect.into_iter();
        (it.next(), it)
   };
   println!("{:?} {:?}", a.unwrap(), bc.collect::<Vec<_>>());
}

Playground

当然,这使您必须检查 and/or 收集到您以后需要的任何内容。如果需要,您可以只使用迭代器。请注意,我使用 into_iter 来消耗向量,但您也可以使用 iter 来处理引用。