Сопоставление с образцом или как использовать операторы для совпадения строк в Scala? - PullRequest
0 голосов
/ 09 сентября 2011

При сопоставлении с образцом в Scala я хотел бы подтвердить не только то, что два String равны, но, например, начинается ли String, заканчивается или содержится в другом и т. Д.

Iэкспериментировал с классами падежей и объектами-экстракторами, не давая мне краткого решения.Итак, решение, которое я придумал, выглядит следующим образом:

class StrMatches(private val str: Option[String]) {

  def ^(prefix: String) = str.exists(_.startsWith(prefix))

  def §(suffix: String) = str.exists(_.endsWith(suffix))

  def %(infix: String) = str.exists(_.contains(infix))

  def ~(approx: String) = str.exists(_.equalsIgnoreCase(approx))

  def /(regex: scala.util.matching.Regex) = str.collect({ case regex() => true }).isDefined

  def °(len: Int) = str.exists(_.length == len)

  def °°(len: (Int, Int)) = str.exists(a => a.length >= len._1 && a.length <= len._2)

  def `\\s*` = str.exists(_.trim.isEmpty)

  override def toString = str.mkString

}

object StrMatches {

  implicit def apply(x: Str) = new StrMatches(x)

  def unapply(x: StrMatches) = x.str

  implicit def unwrap(x: StrMatches) = x.toString

}

Клиент, использующий класс StrMatches, может выглядеть следующим образом:

object TestApp extends App {
  val str = "foobar"
  val strMatches = StrMatches(str)
  if (strMatches ^ "foo") {
    println(strMatches)
  }
  if (strMatches § "bar") {
    println(strMatches)
  }
  if (strMatches % "ob") {
    println(strMatches)
  }
}

В отличие от записи:

object TestApp extends App {
  val str: String = null // Just as an illustration for Scala interfacing Java.
  if (str != null) {
    if (str.startsWith("foo")) {
      println(str)
    }
    if (strMatches.endsWith("bar")) {
      println(str)
    }
    if (strMatches.contains("ob")) {
      println(strMatches)
    }
  }
}

Какие решения вы бы предложили?

1 Ответ

0 голосов
/ 11 сентября 2011

Вы можете использовать регулярные выражения. Тогда вы могли бы использовать сопоставление с образцом (которое, я думаю, было первоначальной целью вашего вопроса):

object TestApp extends App {
    val str = "foobar"

    val StartsWithFooRE = """^foo.*""".r
    val EndsWithBarRE = """.*bar$""".r
    val ContainsBoRE = """.*bo.*""".r

    str match {
        case StartsWithFooRE() => println(str)
        case EndsWithBarRE() => println(str)
        case ContainsBoRE() => println(str)
        case _ =>
    }
}

Чтобы сделать это более удобным, вы можете определить объект с помощью фабричных методов для создания регулярных выражений. Однако из-за того, как работает сопоставление с образцом, вам все равно придется определять выражения вне совпадения:

import scala.util.matching.Regex

object RegexFactory {
    def startsWith(str: String) = new Regex("^%s.*" format str)
    def endsWith(str: String) = new Regex(".*%s$" format str)
    def contains(str: String) = new Regex(".*%s.*" format str)
}


object TestApp extends App {    
    val str = "foobar"

    import RegexFactory._

    val StartsWithFooRE = startsWith("foo")
    val EndsWithBarRE = endsWith("bar")
    val ContainsBoRE = contains("bo")

    str match {
        case StartsWithFooRE() => println(str)
        case EndsWithBarRE() => println(str)
        case ContainsBoRE() => println(str)
        case _ =>
    }
}
...