我有以下代码来进行正则表达式模式匹配。
class UserAgent(val ua: String) {
val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
val Android = """.*Android ([0-9.]+).*""".r
val WindowsPhone = """.*Windows Phone OS.*""".r
val WebOS = """.*webOS.*""".r
val BlackBerry = """.*BlackBerry.*""".r
val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r
var platform = "UnknownPlatform"
var platformVersion = "UnknownVersion"
ua match {
case iOS(_, version) => {
platform = "IOS"
platformVersion = version.replace("_", ".")
}
case Android(version) => {
platform = "Android"
platformVersion = version
}
case WindowsPhone() => platform = "WindowsPhone"
case WebOS() => platform = "WebOS"
case BlackBerry() => platform = "BlackBerry"
case WAPBrowser(p) => platform = "WAPBrowser"
}
}
可以使用(简化)代码进行测试:
val tests = for (
str <- List("Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",
"Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"bla bla Windows Phone OS bla bla",
"bla bla webOS bla bla",
"bla bla BlackBerry bla bla",
"LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1")
) yield new UserAgent(str)
tests foreach { ua => println(ua.platform + " " + ua.platformVersion) }
由于我的班级UserAgent
具有可变变量platform
和platformVersion
,因此这不太可靠。我想要实现的是具有不变性,因此要定义trait
定义platform
和platformVersion
以及将返回不同值的子类。我缺少的是如何创建一个构造函数,它将实例化并返回这样的子类。
答案 0 :(得分:4)
您可以使用Tuple2
:
val (platform, platformVersionOpt) = ua match {
case iOS(_, version) => "IOS" -> Some(version.replace("_", "."))
case Android(version) => "Android" -> Some(version)
case WindowsPhone() => "WindowsPhone" -> None
case WebOS() => "WebOS" -> None
case BlackBerry() => "BlackBerry" -> None
case WAPBrowser(p) => "WAPBrowser" -> None
}
val platformVersion = platformVersionOpt.getOrElse("UnknownPlatform")
Scala方法是使用unapply
方法创建对象:
object UserAgent {
val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
val Android = """.*Android ([0-9.]+).*""".r
val WindowsPhone = """.*Windows Phone OS.*""".r
val WebOS = """.*webOS.*""".r
val BlackBerry = """.*BlackBerry.*""".r
val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r
def unapply(ua: String): Option[(String, Option[String])] = ua match {
case iOS(_, version) => Some("IOS" -> Some(version.replace("_", ".")))
case Android(version) => Some("Android" -> Some(version))
case WindowsPhone() => Some("WindowsPhone" -> None)
case WebOS() => Some("WebOS" -> None)
case BlackBerry() => Some("BlackBerry" -> None)
case WAPBrowser(p) => Some("WAPBrowser" -> None)
case _ => None
}
}
用法:
scala> val tests = List("Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7", "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "bla bla Windows Phone OS bla bla", "bla bla webOS bla bla", "bla bla BlackBerry bla bla", "LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1")
scala> tests foreach {
| case UserAgent(p, v) => println(p + " " + v.getOrElse("UnknownVersion"))
| case _ => println("UnknownPlatform UnknownVersion")
| }
IOS 4.0
Android 2.2
WindowsPhone UnknownVersion
WebOS UnknownVersion
BlackBerry UnknownVersion
WAPBrowser UnknownVersion
答案 1 :(得分:1)
一个可能的答案,使用Tuple2
和Option[String]
作为版本。
我还将正则表达式移动到了伴侣对象。
object UserAgent {
val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
val Android = """.*Android ([0-9.]+).*""".r
val WindowsPhone = """.*Windows Phone OS.*""".r
val WebOS = """.*webOS.*""".r
val BlackBerry = """.*BlackBerry.*""".r
val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r
}
class UserAgent(val ua: String) {
import UserAgent._
val (platform, version): (String, Option[String]) = ua match {
case iOS(_, version) =>
("IOS", Some(version.replace("_", ".")))
case Android(version) =>
("Android", Some(version))
case WindowsPhone() =>
("WindowsPhone", None)
case WebOS() =>
("WebOS", None)
case BlackBerry() =>
("BlackBerry", None)
case WAPBrowser(p) =>
("WAPBrowser", None)
}
}