模式匹配或如何在Scala中进一步利用运算符进行字符串匹配?

时间:2011-09-08 23:57:27

标签: scala operators pattern-matching string-comparison comparison-operators

使用Scala的模式匹配,我不仅要确认两个String是否相等,例如,String是否以#,1开头,是否包含在另一个等等中。

我尝试了案例类和提取器对象,但没有给我一个简洁的解决方案。所以我提出的解决方案如下所示:

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 :(得分:0)

您可以使用正则表达式。然后你可以使用模式匹配(我认为这是你问题的原始意图):

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