web-dev-qa-db-ja.com

文字列パターンマッチングのベストプラクティス

以下は機能しないコードですが、それは私が何をしたいのかを説明しています。

この問題に対する最善のアプローチをお勧めしていただけませんか?

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
  }
}
28
Nikita Volkov

構文に関しては、caseステートメントを少しだけ変更できます。

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

これは、値urlをパターン式(これもurlです)にバインドし、テストでガード式を追加します。これでコードがコンパイルされます。

これをもう少しスカラのようにするために、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
}

これは、例外を管理する場合を除いてです。

42
huynhjl

これが別の方法です。すべてのマッピングをマップに保存し、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)
10
missingfaktor

開始中Scala 2.13Stringsをパターンマッチングすることは可能です 文字列補間を適用解除

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

次に、私たちの場合、Mapを使用して、抽出された値(SQL方言)を適切なドライバーにマッピングするだけです。

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"

不正な形式の入力が予想される場合は、matchステートメントを使用することもできます。

"jdbc:postgresql:something" match {
  case s"jdbc:$dialect:$rest" => Some(dialect)
  case _                      => None
}
// Option[String] = Some("postgresql")
3
Xavier Guihot
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)
0
Volty De Qua