微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

过滤迭代器中与模式匹配的值的惯用方式

如何解决过滤迭代器中与模式匹配的值的惯用方式

在下面的示例(here is the Rust playground)中,我需要在迭代器中过滤与特定模式匹配的值。

我发现的一种方法是使用match返回Option中的filter_map

#[derive(copy,Clone,Debug)]
struct Entity(i32);

enum Event {
    EntityInserted(Entity),EntityRemoved(Entity),}

fn main() {
    let [entity1,entity2] = [Entity(1),Entity(2)];

    let events = vec![
        Event::EntityInserted(entity1),Event::EntityRemoved(entity1),Event::EntityInserted(entity2),];

    let inserted_entities: Vec<_> = events
        .iter()
        .filter_map(|event| match event {                  // <--- 
            Event::EntityInserted(entity) => Some(entity),// <--- Those lines
            _ => None,// <---    here
        })                                                 // <---
        .collect();

    dbg!(inserted_entities);
}

是否有更惯用的方式来发生这种行为?

解决方法

对于filter_map,我认为这是要走的路。

奇怪的是,昨天我写了一个宏,如果Some是“成功”,则生成一个if,否则会得出None

macro_rules! if_then_some {
    ($cond: expr,$val: expr) => {
        if $cond { Some($val) } else { None }
    };
    (let $pattern:pat = $expr: expr,$val: expr) => {
        if let $pattern = $expr { Some($val) } else { None }
    };
}

就目前而言,它可用于检查bool-条件和if let-条件。在您的情况下,可以使用like this

let inserted_entities: Vec<_> = events
    .iter()
    .filter_map(|event|
        if_then_some!(let Event::EntityInserted(entity)=event,entity)
    )
    .collect();

如果这是“惯用的”,这是有争议的,但是恕我直言,它简洁而又易读。

有点题外话:另一方面,每当我看到if let带有OptionResult以外的其他内容时,我都会警惕如果我添加了在这种情况下应检查的新变体,则编译器不会警告我。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。