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种类型:Valid
和Not valid
。
是否可以按值 select 随机 MyEnum
?
例如我想 select 随机 MyEnum
即 Valid
.
这应该可以满足您的需求:
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 objects
或 case 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
一样在模式匹配详尽性检查方面存在问题。
享受
所以我有这个 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种类型:Valid
和Not valid
。
是否可以按值 select 随机 MyEnum
?
例如我想 select 随机 MyEnum
即 Valid
.
这应该可以满足您的需求:
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 objects
或 case 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
一样在模式匹配详尽性检查方面存在问题。
享受