rust 使用迭代查找集合中的特定枚举变量

bprjcwpo  于 2023-03-12  发布在  其他
关注(0)|答案(3)|浏览(119)
设置

我有一个枚举,它的变体有结构参数,沿着枚举的向量:

struct A { x: i64, };
struct B { x: f64, },
enum E {
   One(A),
   Two(B),
   // maybe others
};
fn main() {
   let v = vec![ One( A { x: 10 } ), Two( B { x : 5. } ), /* others as well */ ];
   // ...
}
任务

v中查找E::Two类型的元素。

问题

什么是简洁的,Rust惯用的方法来做到这一点?

首选方法

使用可迭代的find()方法,而不用在AB上派生或实现EqPartialEq,因为 * 我想找到相同枚举变量的东西 *;我并不关心变量的内容,另外,派生EqPartialEq是多余的,而且可能会很痛苦。

9nvpjoqh

9nvpjoqh1#

您可以使用内置的matches!宏来简化此操作:

let found_item = v.iter().find(|i| matches!(i, E::Two(_)));

使用宏是编写以下等效代码的一种更简洁的方法:

let found_item = v.iter().find(|i| match i {
    E::Two(_) => true,
    _ => false,
});

在这两种情况下,found_item的类型都是Option<&E>,如果你只想知道这样的元素是否存在,你可以在这个结果上调用.is_some(),或者你可以使用Iterator::any(),它只返回一个bool来指示是否找到了匹配的元素:

let is_found = v.iter().any(|i| matches!(i, E::Two(_)));

如果你想知道找到的项目的 index,你可以使用Iterator::position()

let index = v.iter().position(|i| matches!(i, E::Two(_)));

index将是Option<usize>,如果找到匹配项,则Option<usize>仅为Some,并且所包含的usize值将是匹配发生处的索引。

vc6uscn9

vc6uscn92#

使用std::mem::discriminant函数:

impl E {
    fn is_two(&self) -> bool {
        mem::discriminant(self) == mem::discriminant(&E::Two(B { x: 0.0 }))
    }
}

v.iter()
.find(|e| e.is_two());
w8f9ii69

w8f9ii693#

这两种可能性都没有使用首选方法。

循环,但不可迭代find

我在网上的某个地方找到了这个(也许甚至如此)

let mut index = 0;
let thing = loop {
    if let E::Two ( b ) = v[index] {
        break Some(b);
    }
    index += 1;
};

可迭代find,但需要派生

ABE类型实现或派生EqPartialEq

let Some(thing) = v.iter().find(|element| if let E::Two(b) = element {true} else {false})
    else {
        panic!("failure! :-("); // I know this won't happen
    };

相关问题