简体   繁体   中英

How to convert a vector of enums into a vector of inner values of a specific variant of that enum

The following code example is the best that I have come up with so far:

enum Variant {
    VariantA(u64),
    VariantB(f64),
}

fn main() {
    let my_vec = vec![Variant::VariantA(1),
                      Variant::VariantB(-2.0),
                      Variant::VariantA(4),
                      Variant::VariantA(3),
                      Variant::VariantA(2),
                      Variant::VariantB(1.0)];

    let my_u64_vec = my_vec
        .into_iter()
        .filter_map(|el| match el {
            Variant::VariantA(inner) => Some(inner),
            _ => None,
        })
        .collect::<Vec<u64>>();

    println!("my_u64_vec = {:?}", my_u64_vec);
}

I would like to know if there is a less verbose way of obtaining the vector of inner values (ie, Vec<u64> in the example). It feels like I might be able to use something like try_from or try_into to make this less verbose, but I cannot quite get there.

Enums are not "special" and don't have much if any implicitly associated magic, so by default yes you need a full match -- or at least an if let eg

if let Variant::VariantA(inner) = el { Some(inner) } else { None }

However nothing prevents you from implementing whatever utility methods you're thinking of on your enum eg get_a which would return an Option<A> (similar to Result::ok and Result::err ), or indeed to implement TryFrom on it:

use std::convert::{TryFrom, TryInto};

enum Variant {
    VariantA(u64),
    VariantB(f64),
}

impl TryFrom<Variant> for u64 {
    type Error = ();

    fn try_from(value: Variant) -> Result<Self, Self::Error> {
        if let Variant::VariantA(v) = value { Ok(v) } else { Err(()) }
    }
}

fn main() {
    let my_vec = vec![Variant::VariantA(1),
                      Variant::VariantB(-2.0),
                      Variant::VariantA(4),
                      Variant::VariantA(3),
                      Variant::VariantA(2),
                      Variant::VariantB(1.0)];

    let my_u64_vec = my_vec
        .into_iter()
        .filter_map(|el| el.try_into().ok())
        .collect::<Vec<u64>>();

    println!("my_u64_vec = {:?}", my_u64_vec);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM