如何解构 &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);
我收到这个错误:
the size for values of type [&str]
cannot be known at compilation time
这是为什么?我能以某种方式解构 &str
的 Vec
吗?
只需添加一个&
:v[..]
是夏令时([T]
,不是 &[T]
)。这很好,只要我们只访问单个元素,但对于生成切片的剩余模式 (..
),它们也必须生成 [T]
,并且未调整大小。另一方面,如果你匹配 &[T]
,其余模式也会给出 &[T]
(另一种可能性是使用 ref
- ref bc @ ..
,但我不建议这样做) .
let [a, bc @ ..] = &str_vect[..];
然而,这失败了:
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 let
或 match
来处理这种情况。
另一种解决方案,绝对不是解构,但在我看来更容易阅读,因为名称表达了意图,将依赖于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<_>>());
}
当然,这使您必须检查 and/or 收集到您以后需要的任何内容。如果需要,您可以只使用迭代器。请注意,我使用 into_iter
来消耗向量,但您也可以使用 iter
来处理引用。
我的情况:
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);
我收到这个错误:
the size for values of type
[&str]
cannot be known at compilation time
这是为什么?我能以某种方式解构 &str
的 Vec
吗?
只需添加一个&
:v[..]
是夏令时([T]
,不是 &[T]
)。这很好,只要我们只访问单个元素,但对于生成切片的剩余模式 (..
),它们也必须生成 [T]
,并且未调整大小。另一方面,如果你匹配 &[T]
,其余模式也会给出 &[T]
(另一种可能性是使用 ref
- ref bc @ ..
,但我不建议这样做) .
let [a, bc @ ..] = &str_vect[..];
然而,这失败了:
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 let
或 match
来处理这种情况。
另一种解决方案,绝对不是解构,但在我看来更容易阅读,因为名称表达了意图,将依赖于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<_>>());
}
当然,这使您必须检查 and/or 收集到您以后需要的任何内容。如果需要,您可以只使用迭代器。请注意,我使用 into_iter
来消耗向量,但您也可以使用 iter
来处理引用。