2011-10-08 27 views
22

我目前正在Scala中迈出第一步,因此我正在寻找解决常见问题的最佳实践。以下是不起作用的代码,但它描述了我想要做的事情。你能否推荐这个问题的最佳方法?匹配最佳实践的Scala字符串模式

def resolveDriver(url: String) = { 
    url match { 
     case url.startsWith("jdbc:mysql:") => "com.mysql.jdbc.Driver" 
     case url.startsWith("jdbc:postgresql:") => "org.postgresql.Driver" 
     case url.startsWith("jdbc:h2:") => "org.h2.Driver" 
     case url.startsWith("jdbc:hsqldb:") => "org.hsqldb.jdbcDriver" 
     case _ => throw new IllegalArgumentException 
    } 
    } 
+2

参见[这个问题](http://stackoverflow.com/q/7586605/53013)另一种方式来解决这个问题,如果匹配的部分碰巧是整个协议。 –

回答

39

在语法方面,你可以修改只是一点点你的case语句:

case url if url.startsWith("jdbc:mysql:") => "com.mysql.jdbc.Driver" 

这只是绑定值url的模式表达式(这也是url),并增加了保护用测试表达。这应该使代码编译。

为了让多一点点阶状,你可以返回一个选项[字符串](我删除了几个条款,因为它只是为了举例说明):

def resolveDriver(url: String) = url match { 
    case u if u.startsWith("jdbc:mysql:") => Some("com.mysql.jdbc.Driver") 
    case u if u.startsWith("jdbc:postgresql:") => Some("org.postgresql.Driver") 
    case _ => None 
} 

也就是说,除非你要管理例外。

+0

谢谢!这正是我所期待的!我很高兴我问了这个问题“因为我已经准备为自己创建一个案例类,这个类似于过度复杂的气味。另外我感谢你纠正我的异常投掷。 –

10

这是另一种方法。将所有映射存储在地图中,然后使用collectFirst方法查找匹配项。的collectFirst类型签名是:

def TraversableOnce[A].collectFirst[B](pf: PartialFunction[A, B]): Option[B] 

用法:

scala> val urlMappings = Map("jdbc:mysql:" -> "com.mysql.jdbc.Driver", "jdbc:postgresql:" -> "org.postgresql.Driver") 
urlMappings: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(jdbc:mysql: -> com.mysql.jdbc.Drive 
r, jdbc:postgresql: -> org.postgresql.Driver) 

scala> val url = "jdbc:mysql:somestuff" 
url: java.lang.String = jdbc:mysql:somestuff 

scala> urlMappings collectFirst { case(k, v) if url startsWith k => v } 
res1: Option[java.lang.String] = Some(com.mysql.jdbc.Driver) 
+0

谢谢,但不是你提出的'匹配'的抽象? –

+0

@mojojojo:不完全。 'match'后面的'case'表达式组成了'PartialFunction'。 'collectFirst'是一个接受'PartialFunction'的方法,循环遍历集合,并返回包含在'Some'中的第一个匹配项。 (如果找不到匹配,则返回“None”。) – missingfaktor

+0

@mojojojo:请参阅源代码:http://goo.gl/Q4UNz – missingfaktor