2017-02-10 282 views
1

裏面我寫了這個代碼使用正則表達式枚舉模式匹配

object Foo extends Enumeration { 
    val X = Value("X") 
    val Y = Value("Y") 
} 

val regex = """([A-Z]+)(\d+)""".r 
val input = "ABC123" 

input match { 
    case regex(x, num) if x == Foo.X.toString => // do something 
    case regex(x, num) if x == Foo.Y.toString => // do something 
    case _ => // throw error 
} 

這工作,但有點太冗長。我試圖將其更改爲

input match { 
    case regex(`Foo.X.toString`, num) => // do something 
    case regex(`Foo.Y.toString`, num) => // do something 
    case _ => // throw error 
} 

但是這不能編譯。這些```爲`vals'工作,但不適用於枚舉。

回答

2

在我看來已經有人問此功能,但大多數人都避免枚舉現在:從任意字符串構造正則表達式的

scala> object E extends Enumeration { 
    | val X, Y = Value 
    | def unapply(s: String): Option[Value] = values.find(_.toString == s) 
    | } 
defined object E 

scala> val r = "([A-Z]+)".r 
r: scala.util.matching.Regex = ([A-Z]+) 

scala> "Y" match { case r(E(e)) => e } 
res0: E.Value = Y 

scala> "Y" match { case r(E(E.Y)) => } 

注的危害:

scala> object E extends Enumeration { val X, Y, Z_* = Value } 
defined object E 

scala> val r = E.values.mkString("|").r 
r: scala.util.matching.Regex = X|Y|Z_$times 

scala> object E extends Enumeration { val X, Y = Value ; val Z = Value("*") } 
defined object E 

scala> val r = E.values.mkString("|").r 
java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 4 
X|Y|* 
    ^
    at java.util.regex.Pattern.error(Pattern.java:1955) 
    at java.util.regex.Pattern.sequence(Pattern.java:2123) 
    at java.util.regex.Pattern.expr(Pattern.java:1996) 
    at java.util.regex.Pattern.compile(Pattern.java:1696) 
    at java.util.regex.Pattern.<init>(Pattern.java:1351) 
    at java.util.regex.Pattern.compile(Pattern.java:1028) 
    at scala.util.matching.Regex.<init>(Regex.scala:209) 
    at scala.collection.immutable.StringLike.r(StringLike.scala:287) 
    at scala.collection.immutable.StringLike.r$(StringLike.scala:287) 
    at scala.collection.immutable.StringOps.r(StringOps.scala:29) 
    at scala.collection.immutable.StringLike.r(StringLike.scala:276) 
    at scala.collection.immutable.StringLike.r$(StringLike.scala:276) 
    at scala.collection.immutable.StringOps.r(StringOps.scala:29) 
    ... 29 elided 

scala> object E extends Enumeration { val X, Y = Value ; val Z = Value(".*") } 
defined object E 

scala> val r = E.values.mkString("|").r 
r: scala.util.matching.Regex = X|Y|.* 

scala> "junk" match { case r() => }