Pick a random value from an enum?
The only thing I would suggest is caching the result of values()
because each call copies an array. Also, don't create a Random
every time. Keep one. Other than that what you're doing is fine. So:
public enum Letter {
A,
B,
C,
//...
private static final List<Letter> VALUES =
Collections.unmodifiableList(Arrays.asList(values()));
private static final int SIZE = VALUES.size();
private static final Random RANDOM = new Random();
public static Letter randomLetter() {
return VALUES.get(RANDOM.nextInt(SIZE));
}
}
How can i pick Random Value from an Enum?
To generate the random number, use ThreadLocalRandom.current().nextInt(0, Animal.values().length)
and retrieve the value from the enum using Animal.values()[randomNumber]
, although it appears you're provided with RandomTools.randomValue
. I've written my own for completeness.
Declare Animal[] values = Animal.values()
once, outside your loop and perform the operations on that to avoid values()
being called more than once.
It should look something like this:
import java.util.concurrent.ThreadLocalRandom;
public class SOExample {
private enum Animal {
ELEPHANT, LION, TIGER, WASP, SNAKE, MONKEY, EMU
}
// It's not clear from the question if you're provided with this or if you have to write it
private static class RandomTools {
public static int randomValue(int start, int end) {
return ThreadLocalRandom.current().nextInt(start, end);
}
}
public static void main(String[] args) {
Animal[] zoo = generateRandomZoo(100);
// Printing to STDOUT to check results
for (int i = 0; i < zoo.length; i++) {
System.out.println(zoo[i]);
}
}
private static Animal[] generateRandomZoo(int numberOfAnimals) {
Animal[] animals = new Animal[numberOfAnimals];
Animal[] values = Animal.values();
for (int i = 0; i < animals.length; i++) {
int random = RandomTools.randomValue(0, values.length);
animals[i] = values[random];
}
return animals;
}
}
How to randomly select an enum value?
// get an array of all the cards
private Card[]cards=Cards.values();
// this generates random numbers
private Random random = new Random();
// choose a card at random
final Card random(){
return cards[random.nextInt(cards.length)];
}
How to get random value from assigned enum in c++?
There is no way to enumerate the values of an enum.
You can use a table:
std::vector<int> colors = {red, black, pink, rainbow};
and then pick a random element from it.
Picking a random element left as an exercise.
How do I select a random value from an enumeration?
Array values = Enum.GetValues(typeof(Bar));
Random random = new Random();
Bar randomBar = (Bar)values.GetValue(random.Next(values.Length));
How to efficiently pick a random element from an enumeration in scala?
Less than a minute with the documentation shows
final def maxId: Int
The one higher than the highest integer amongst those used to identify values in this enumeration.
and
final def apply(x: Int): Value
The value of this enumeration with given id x
So
Animals(scala.util.Random.nextInt(Animals.maxId))
//> res0: recursion.recursion.Animals.Value = Monkey
(assuming all values are used, and you didn't pass in an initial value to the constructor)
Or you could enumerate the values with Animals.values
and then refer to this question
How do I choose a random value from an enum?
Your own enum
Like most abstractions in Rust, random value generation is powered by traits. Implementing a trait is the same for any particular type, the only difference is exactly what the methods and types of the trait are.
Rand 0.5, 0.6, 0.7, and 0.8
Implement Distribution
using your enum as the type parameter. You also need to choose a specific type of distribution; Standard
is a good default choice. Then use any of the methods to generate a value, such as rand::random
:
use rand::{
distributions::{Distribution, Standard},
Rng,
}; // 0.8.0
#[derive(Debug)]
enum Spinner {
One,
Two,
Three,
}
impl Distribution<Spinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Spinner {
// match rng.gen_range(0, 3) { // rand 0.5, 0.6, 0.7
match rng.gen_range(0..=2) { // rand 0.8
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let spinner: Spinner = rand::random();
println!("{:?}", spinner);
}
Rand 0.4
Implement Rand
for your enum, then use any of the methods to generate a value, such as Rng::gen
:
extern crate rand; // 0.4.2
use rand::{Rand, Rng};
#[derive(Debug)]
enum Spinner {
One,
Two,
Three,
}
impl Rand for Spinner {
fn rand<R: Rng>(rng: &mut R) -> Self {
match rng.gen_range(0, 3) {
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinner: Spinner = rng.gen();
println!("{:?}", spinner);
}
Derive
The rand_derive
crate can remove the need for some of this boilerplate, but does not exist for Rand 0.5.
extern crate rand;
#[macro_use]
extern crate rand_derive;
use rand::Rng;
#[derive(Debug, Rand)]
enum Spinner {
One,
Two,
Three,
}
fn main() {
let mut rng = rand::thread_rng();
let spinner: Spinner = rng.gen();
println!("{:?}", spinner);
}
Someone else's enum
Since you don't control the enum, you have to copy something into your code in order to reference it. You could create an array of the enum and choose
from that:
use rand::seq::SliceRandom; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinners = [
another_crate::Spinner::One,
another_crate::Spinner::Two,
another_crate::Spinner::Three,
];
let spinner = spinners.choose(&mut rng).unwrap();
println!("{:?}", spinner);
}
You could replicate the entire enum locally, implement Rand
for that, and then have a method that converts back into the other crates representation.
use rand::{
distributions::{Distribution, Standard},
Rng,
}; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
enum Spinner {
One,
Two,
Three,
}
impl From<Spinner> for another_crate::Spinner {
fn from(other: Spinner) -> another_crate::Spinner {
match other {
Spinner::One => another_crate::Spinner::One,
Spinner::Two => another_crate::Spinner::Two,
Spinner::Three => another_crate::Spinner::Three,
}
}
}
impl Distribution<Spinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Spinner {
match rng.gen_range(0..=2) {
0 => Spinner::One,
1 => Spinner::Two,
_ => Spinner::Three,
}
}
}
fn main() {
let spinner = another_crate::Spinner::from(rand::random::<Spinner>());
println!("{:?}", spinner);
}
You could count the number of spinners and do a match:
use rand::Rng; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
fn rando<R: Rng>(mut rng: R) -> another_crate::Spinner {
match rng.gen_range(0..=2) {
0 => another_crate::Spinner::One,
1 => another_crate::Spinner::Two,
_ => another_crate::Spinner::Three,
}
}
fn main() {
let mut rng = rand::thread_rng();
let spinner = rando(&mut rng);
println!("{:?}", spinner);
}
You can implement a newtype and implement the random generation for that:
use rand::{distributions::Standard, prelude::*}; // 0.8.0
mod another_crate {
#[derive(Debug)]
pub enum Spinner {
One,
Two,
Three,
}
}
struct RandoSpinner(another_crate::Spinner);
impl Distribution<RandoSpinner> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> RandoSpinner {
RandoSpinner(match rng.gen_range(0..=2) {
0 => another_crate::Spinner::One,
1 => another_crate::Spinner::Two,
_ => another_crate::Spinner::Three,
})
}
}
fn main() {
let RandoSpinner(spinner) = rand::random();
println!("{:?}", spinner);
}
See also:
- How do I implement a trait I don't own for a type I don't own?
How to pick up a random value from an enum class?
Since you have a XMacro already, you can just reuse it to create an array of the values and pick from it:
const Niveau niveau_vals[] = {
#define NIVEAU_DEF(NOM,VALEUR) Niveau::VALEUR,
#include "niveau.def"
#undef NIVEAU_DEF
};
In newer versions of the language, you can make it a nice constexpr with std::array
.
constexpr std::array niveau_vals = {
#define NIVEAU_DEF(NOM,VALEUR) Niveau::VALEUR,
#include "niveau.def"
#undef NIVEAU_DEF
};
How to select a random enumeration value with limitations based on the current enumeration value?
You can write the possible directions for each case by hand:
use rand::prelude::*;
use Direction::*;
#[derive(Debug, PartialEq, Copy, Clone)]
enum Direction {
Up,
Right,
Down,
Left,
}
impl Direction {
fn next_random(self) -> Self {
match self {
Up => [Up, Left, Right],
Down => [Down, Left, Right],
Left => [Up, Down, Left],
Right => [Up, Down, Right],
}
.choose(&mut thread_rng())
.copied()
.unwrap()
}
}
Of course, if your enum has a lot of variants, it's better to have a more generic solution:
impl Direction {
fn all() -> &'static [Self] {
&[Up, Down, Left, Right]
}
fn opposite(self) -> Self {
match self {
Up => Down,
Down => Up,
Left => Right,
Right => Left,
}
}
fn next_random(self) -> Self {
let next = Self::all()
.iter()
.filter(|&&d| d != self.opposite())
.choose(&mut thread_rng());
*next.unwrap()
}
}
Note that if you want better performances or flexibility, you may pass the random number generator as a parameter:
fn next_random(self, rng: &mut impl Rng) -> Self {
let next = Self::all()
.iter()
.filter(|&&d| d != self.opposite())
.choose(rng);
*next.unwrap()
}
Related Topics
How to Reuse Code for Selecting a Custom Dto Object for a Child Property with Ef Core
How to Use Transactionscope in C#
Difference Between Select and Convertall in C#
Simplest Way to Run Three Methods in Parallel in C#
Is There a Format Code Shortcut for Visual Studio
How to Tell If a Type Is a "Simple" Type? I.E. Holds a Single Value
Use Different Name for Serializing and Deserializing with JSON.Net
Forms' Does Not Exist in the Namespace System.Windows
How to Change the Button Text for 'Yes' and 'No' Buttons in the Messagebox.Show Dialog
How to Override with Derived Types
Resize Wpf Window and Contents Depening on Screen Resolution
Binding Combobox Selecteditem Using Mvvm
Contextswitchdeadlock Was Detected Error in C#
Eager , Lazy and Explicit Loading in Ef6
Closures Behaving Differently in for and Foreach Loops