scala 字符串模式匹配最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7698815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:33:09  来源:igfitidea点击:

String pattern matching best practice

scalapattern-matching

提问by Nikita Volkov

Following is the code that doesn't work but it describes what I want to do.

以下是不起作用的代码,但它描述了我想要做什么。

Could you please recommend the best approach to this problem?

您能否推荐解决此问题的最佳方法?

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
  }
}

回答by huynhjl

In terms of syntax, you can modify just a tiny bit you case statements:

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

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

This simply binds the value urlto the pattern expression (which is also url) and adds a guard expression with a test. That should make the code compile.

这只是将值绑定url到模式表达式(也是url)并添加一个带有测试的保护表达式。这应该使代码编译。

To make it a little bit more scala-like, you can return an Option[String] (I removed a couple clause since it's just for illustration):

为了让它更像 Scala,你可以返回一个 Option[String] (我删除了几个子句,因为它只是为了说明):

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
}

That is unless you want to manage exceptions.

除非您想管理异常。

回答by missingfaktor

Here is an alternate way. Store all the mappings in a map and then use collectFirstmethod to find the match. Type signature of collectFirstis:

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

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

Usage:

用法:

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)

回答by Xavier Guihot

Starting Scala 2.13, it's possible to pattern match a Strings by unapplying a string interpolator:

开始Scala 2.13,可以String通过不应用字符串插值器来模式匹配s :

val s"jdbc:$dialect:$rest" = "jdbc:mysql:whatever"
// dialect: String = "mysql"
// rest: String = "whatever"

Then in our case, it's just a matter of mapping the extracted value (the sql dialect) to the appropriate driver using a Map:

然后在我们的例子中,只需使用以下命令将提取的值(sql 方言)映射到适当的驱动程序Map

val drivers = Map(
  "postgresql" -> "org.postgresql.Driver",
  "mysql"      -> "com.mysql.jdbc.Driver",
  "h2"         -> "org.h2.Driver"
)
val driver = drivers(dialect)
// driver: String = "com.mysql.jdbc.Driver"


If you are expecting malformed inputs, you can also use a match statement:

如果您期待格式错误的输入,您还可以使用 match 语句:

"jdbc:postgresql:something" match {
  case s"jdbc:$dialect:$rest" => Some(dialect)
  case _                      => None
}
// Option[String] = Some("postgresql")

回答by Volty De Qua

import PartialFunction._  // condOpt

val drivers = Map( 
  "mysql" -> "mysql driver",
  "h2" -> "h2 driver" 
  // ... 
)
val pattern = "^jdbc:(\w+):.*".r

def resolveDriver(url: String) = condOpt(url) { 
  case pattern(dbms) => drivers.get(dbms) 
}.flatten.getOrElse(throw new IllegalArgumentException)