Select 按值随机枚举

Select random Enumeration by value

所以我有这个 Enumeration:

object MyEnum extends Enumeration {
  val a = Value(0, "Valid")
  val b = Value(1, "Valid")
  val c = Value(2, "Not Valid")
  val d = Value(3, "Not Valid")
}

这个Enumeration包含2种类型:ValidNot valid。 是否可以按值 select 随机 MyEnum

例如我想 select 随机 MyEnumValid.

这应该可以满足您的需求:

val valids = MyEnum.values.filter { _.toString.equalsIgnoreCase("Valid") }.toSeq
val selected = valids(util.Random.nextInt(valids.length))

println(s"Selected $selected with id: ${selected.id}")

你可以使用scala Random:

scala.util.Random.shuffle(MyEnum.values.toList).find(_.toString.equalsIgnoreCase("Valid"))

它会return一个选项

即使 Yuval 的答案正确并且解决方案有效,也不建议使用 Enumeration 编码额外的 属性。通过使用 name 字段将类型编码为 Value"Valid""Not Valid"(或任何其他 class 化),您正在失去构建能力Enumeration class 通过 .withName 方法从 String 重建枚举值实例:

// result will be always `a` for "Valid" and `b` for "Not Valid"
// it will throw an NoSuchElementException for any other string
MyEnum.withName(someString) 

简而言之,当您只是滥用 name 字段来 class 枚举值实例化时。如果这在您的代码中不是问题,那么您很幸运,但无论如何要非常准确地记录滥用情况。

Enumeration 旨在表达简单的值,它有一个索引并且可以有很好的人类可读名称。就是这样,不多不少。

经验法则是,当您有一个需要其他字段的枚举时,最好使用 case objectscase classes 的密封层次结构对其进行建模。类似的东西(只是针对您的特定情况的示例):

// Hierarchy is sealed, thus you will get can pattern match with check for exhaustiveness
sealed trait MyEnum {
  def id: Int
  def name: String
  def valid: Boolean
}
// Helper case class, which allows to not define
private case class Value(id: Int, name: String, valid: Boolean) extends MyEnum

object MyEnum {  
  // Your values
  val A: MyEnum = Value(0, "My A", true)
  val B: MyEnum = Value(1, "My B", true)
  val C: MyEnum = Value(0, "My A", false)
  val D: MyEnum = Value(1, "My B", false)

  // Re-implementation of methods contained in Enumeration, pick what you need
  val values: Seq[MyEnum] = Seq(A, B, C, D)
  // You can implement your own semantics, e.g. no Exception rather Option
  def withName(name: String): Option[MyEnum] = values.find( _.name == name )

  // Methods already for your example
  val valids: Seq[MyEnum] = values.filter( _.valid )
  // Or with randomization build in to enum
  def randomValid: MyEnum = valids(util.Random.nextInt(valids.length))
}

此外,您将获得更多的类型安全性:

// More type safety, fn simple does not compile
def fn(value: MyEnum) = value match {
  case MyEnum.A => true
}

<console>:14: warning: match may not be exhaustive.
It would fail on the following input: Value(_, _, _)
       def fn(value: MyEnum) = value match {
                               ^
fn: (value: MyEnum)Boolean

您的经验可能会有所不同,因为在 Scala 中编写枚举的可能性几乎是无穷无尽的:) 在我的示例中,我只展示了许多可能实现中的一种。如果您有很多值,上述方法可能不切实际。

要了解有关使用 Enumeration 的缺点的更多信息,请参阅 "Scala Enumerations" 博客 post。 请注意,文章末尾的解决方案不是灵丹妙药,并且与 Enumeration 一样在模式匹配详尽性检查方面存在问题。

享受