2016-03-03 53 views
1

隨機枚舉所以我有這個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。 是否可以按價值選擇隨機MyEnum

例如,我要選擇一個隨機MyEnumValid

回答

2

即使尤瓦的回答是正確的解決方案將工作,使用Enumeration編碼附加屬性不建議。通過使用name字段中爲Value是你正在失去建立在從String經由.withName方法來重構枚舉值實例Enumeration類的能力的編碼類型作爲"Valid""Not Valid"(或任何其他分類):

// 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可能會有所不同,因爲在斯卡拉寫一個枚舉可能性幾乎無盡:)在我的例子中,我只展示了許多可能的實現中的一種。如果你有很多上面提到的方法可能是不切實際的。

要了解更多關於使用Enumeration看到"Scala Enumerations"博客文章的缺點。 當心文章的結尾這種解決辦法是不銀子彈,並與模式匹配全面性檢查作爲Enumeration確實問題。

享受

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

您可以使用Scala的隨機:

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

,它會返回一個選項