< 返回版块

githik999 发表于 2022-06-20 20:22

enum Direction { NORTH, SOUTH, EAST, WEST, }

for direction in Direction::iter() { println!("{:?}", direction); }

类似这样的

最好简单一点的 有没有这种东西 貌似没找到

评论区

写评论
一叶微尘 2023-05-17 17:11

用strum库即可


// You need to bring the trait into scope to use it!
use strum::IntoEnumIterator;
use strum_macros::EnumIter;

#[derive(EnumIter, Debug, PartialEq)]
enum Color {
    Red,
    Green { range: usize },
    Blue(usize),
    Yellow,
}

// It's simple to iterate over the variants of an enum.
for color in Color::iter() {
    println!("My favorite color is {:?}", color);
}

let mut ci = Color::iter();
assert_eq!(Some(Color::Red), ci.next());
assert_eq!(Some(Color::Green {range: 0}), ci.next());
assert_eq!(Some(Color::Blue(0)), ci.next());
assert_eq!(Some(Color::Yellow), ci.next());
assert_eq!(None, ci.next());
Lich 2022-07-01 20:10

用const定义enum option的数量,但也要同时实现From数字类型到enum的类型转换,这样可以通过遍历数字来便利enum。

use std::convert::TryFrom;

#[derive(Debug)]
enum Direction {
    North,
    South,
    East,
    West,
}

impl TryFrom<u8> for Direction {
    type Error = String;
    fn try_from(v: u8) -> Result<Self, Self::Error> {
        match v {
            0 => Ok(Self::North),
            1 => Ok(Self::South),
            2 => Ok(Self::East),
            3 => Ok(Self::West),
            n => Err(format!("Given number {} is out of range",n)),
        }
    }
}

impl Direction {
    const NUM_OF_OPTION: u8  = 4;
}


fn main() {
    for d in 0..Direction::NUM_OF_OPTION {
        println!("{} Direction is {:?}", d, Direction::try_from(d).ok());
    }
}

--
👇
githik999: 要是用这种const方式的话感觉很痛苦啊...特别这个enum很长的时候 不是要写两遍?而且增删也很不方便 现在只能先用第三方库了.第三方库自己又引入了好多个第三方库...醉了

--
👇
苦瓜小仔: 如果你有很多这样的枚举体,用第三方库最省事。

如果你不想引入库,使用 const 就好了:

use Direction::*;
fn main() {
    for direction in Direction::DIRECTION {
        println!("{:?}", direction);
    }
}

#[derive(Debug)]
enum Direction {
    NORTH,
    SOUTH,
    EAST,
    WEST,
}

impl Direction {
    const DIRECTION: [Self; 4] = [NORTH, SOUTH, EAST, WEST];
}
stevefan1999-personal 2022-06-28 20:20

https://docs.rs/strum/latest/strum/

DogLi 2022-06-24 13:36

这玩意儿不应该使用match?就算你能for,for了之后你怎么做?还不是要用 match 或者 maches! 或者 if之类的东西

Aya0wind 2022-06-21 13:46

不如自己写一个derive macro,加一个迭代器的实现,把成员放到数组里然后返回数组迭代器,对于不可遍历的枚举直接编译报错,仅仅是自用的话其实还算简单。

Neutron3529 2022-06-21 00:53

好像问题在于,并不是每一个enum都是可以遍历的

如果你想遍历,你不可避免地要处理Option<i32>的遍历问题

大概是这个特性导致了enum没有公共的遍历方法

作者 githik999 2022-06-20 21:54

要是用这种const方式的话感觉很痛苦啊...特别这个enum很长的时候 不是要写两遍?而且增删也很不方便 现在只能先用第三方库了.第三方库自己又引入了好多个第三方库...醉了

--
👇
苦瓜小仔: 如果你有很多这样的枚举体,用第三方库最省事。

如果你不想引入库,使用 const 就好了:

use Direction::*;
fn main() {
    for direction in Direction::DIRECTION {
        println!("{:?}", direction);
    }
}

#[derive(Debug)]
enum Direction {
    NORTH,
    SOUTH,
    EAST,
    WEST,
}

impl Direction {
    const DIRECTION: [Self; 4] = [NORTH, SOUTH, EAST, WEST];
}
作者 githik999 2022-06-20 21:50

非常感谢.这个需求crates.io上面有好几个第三方库 下载量还挺高的你别说

--
👇
苦瓜小仔: 当然,你也可以选择 trait 来抽象遍历枚举:

pub trait EnumIter
where
    Self: Sized + 'static,
{
    const ITER: &'static [Self];
}

playground

那个 RFC 2014 年到现在没什么人推动,说明这不是大多数人的刚需。

苦瓜小仔 2022-06-20 21:33

当然,你也可以选择 trait 来抽象遍历枚举:

pub trait EnumIter
where
    Self: Sized + 'static,
{
    const ITER: &'static [Self];
}

playground

那个 RFC 2014 年到现在没什么人推动,说明这不是大多数人的刚需。

苦瓜小仔 2022-06-20 21:17

如果你有很多这样的枚举体,用第三方库最省事。

如果你不想引入库,使用 const 就好了:

use Direction::*;
fn main() {
    for direction in Direction::DIRECTION {
        println!("{:?}", direction);
    }
}

#[derive(Debug)]
enum Direction {
    NORTH,
    SOUTH,
    EAST,
    WEST,
}

impl Direction {
    const DIRECTION: [Self; 4] = [NORTH, SOUTH, EAST, WEST];
}
作者 githik999 2022-06-20 20:47

这个我知道 找了一圈貌似官方还真没有这种东西

https://github.com/rust-lang/rfcs/issues/284

这个rfc是不是还没有实现啊?

--
👇
苦瓜小仔: https://stackoverflow.com/questions/21371534/in-rust-is-there-a-way-to-iterate-through-the-values-of-an-enum

苦瓜小仔 2022-06-20 20:33

https://stackoverflow.com/questions/21371534/in-rust-is-there-a-way-to-iterate-through-the-values-of-an-enum

1 共 12 条评论, 1 页