rust 有没有一种简单的方法可以从一个“Vec”中提取出一个元素?

eanckbw9  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(128)

我有一个对Vec的引用,我想从中提取一个对一个元素的引用,如果有更多的元素或零,则会出现恐慌。如果我有一个数组,则等效于:

let [x] = list;

字符串
但是Vec的大小是动态的,所以在这里不起作用。我可以想到一种方法来引用Vec,还有几种需要所有权的方法,但是我想知道是否有一种更短更简单的方法。

Unowned选项1:使用assert!和索引

assert_eq!(list.len(), 1);
let x = &list[0];

自带选项1:使用try_into()

let [x]: [i32; 1] = list.try_into().unwrap();

自带选项2:使用assert!pop

assert_eq!(list.len(), 1);
let x = list.pop();


那么,有没有更简单、更明确的方法呢?

vs91vp4v

vs91vp4v1#

您可以将slice patternlet else结合使用:

let v = vec![1u32];
let &[x] = v.as_slice() else {
    panic!("expected single element"); // or return, break, etc.
};
assert_eq!(x, 1);

字符串
Playground
它不一定比您的选项短,但它清晰且相当简洁,不需要所有权或变更,并且可以很好地概括为多个元素进行提取。
如果你不想惊慌,而是想检查元素计数并提取x(如果它是唯一的元素),你可以使用if let

if let &[x] = v.as_slice() {
   // ... use x ...
}

已编辑

这个答案最初建议使用更详细的match语法,在Rust 1.65中引入let else之前,这是强制性的。如果您正在为支持旧编译器的项目做出贡献,或者如果您发现let else不受欢迎,它仍然很有用:

let x = match v.as_slice() {
    &[x] => x,
    _ => panic!("expected single element"),
};

sgtfey8w

sgtfey8w2#

使用itertools,适用于自有和非自有版本:

use itertools::Itertools;

// Reference
let x = list.iter().exactly_one().expect("more or less than one");
// Owned
let x = list.into_iter().exactly_one().expect("more or less than one");

字符串

相关问题