How do I choose a random value from an enum?

后端 未结 2 1301
逝去的感伤
逝去的感伤 2021-01-08 00:22

The spinners crate has an enum with a large selection of possible spinners.

Here\'s the enum (with all values except the top and bottom 4 skipped):

p         


        
2条回答
  •  孤街浪徒
    2021-01-08 01:02

    Since Shepmaster asked I can suggest another couple of options.

    Unfortunately rng.choose(Spinners) cannot work because there is no way to iterate over enum values; see: In Rust, is there a way to iterate through the values of an enum?

    You could presumably use strum's EnumIter to allow iteration. In Rand 0.4 and 0.5, choose does not support iterators, but you could either collect all options into a Vec or enumerate and match the index. In Rand 0.6, there will be a variant of choose supporting iterators, although it may quite slow (depending on whether we can optimise it for ExactSizeIterators).

    use rand::prelude::*;
    
    #[derive(EnumIter)]
    enum Spinner { ... }
    
    let mut rng = thread_rng();
    
    let options = Spinner::iter().collect::>();
    let choice = rng.choose(&options);
    
    // or:
    let index = rng.gen_range(0, MAX);
    let choice = Spinner::iter().enumerate().filter(|(i, _)| i == index).map(|(_, x)| x).next().unwrap();
    
    // with Rand 0.6, though this may be slow:
    let choice = Spinner::iter().choose(&mut rng);
    // collecting may be faster; in Rand 0.6 this becomes:
    let choice = Spinner::iter().collect::>().choose(&mut rng);
    

    Another option is to use num's FromPrimitive trait with num-derive:

    #[derive(FromPrimitive)]
    enum Spinner { ... }
    
    let choice = Spinner::from_u32(rng.gen_range(0, MAX)).unwrap();
    

提交回复
热议问题