按值选择随机枚举

时间:2016-03-03 20:45:10

标签: scala enumeration

所以我有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包含两种类型:ValidNot valid。 是否可以按值选择随机MyEnum

例如,我想选择MyEnum的随机Valid

3 个答案:

答案 0 :(得分:2)

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

// 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字段来分类你的枚举值实例时,简单地说。如果这不是您的代码中的问题,那么您就是一个幸运的人,但无论如何都要非常准确地记录误用。

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

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

要详细了解使用Enumeration的缺点,请参阅"Scala Enumerations"博文。 请注意文章末尾的解决方案不是银弹,并且模式匹配穷举检查存在问题{/ 1}}。

享受

答案 1 :(得分:0)

这应该做你需要的:

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}")

答案 2 :(得分:0)

你可以使用scala Random:

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

它会返回一个选项