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

发布于 2024-12-03 13:32:03 字数 1719 浏览 1 评论 0原文

通过 Scala 的模式匹配,我不仅想确认两个 String 是否相等,还想确认一个 String 是否以另一个字符串开头、结尾或包含在另一个字符串中,等等。

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

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

您会提出什么样的解决方案?

With Scala's pattern matching I would like to confirm not only that two Strings are equal but for example, whether a String starts with, ends, or is contained in another etc.

I experimented with case classes and extractor objects, neither giving me a concise solution. So the solution I came up with looks like the following:

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

}

A client using the StrMatches class could look like the following:

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

As opposed to writing:

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

With what kind of solutions would you come up with?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮年 2024-12-10 13:32:03

您可以使用正则表达式。然后您可以使用模式匹配(我认为这是您问题的初衷):

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

You could use regular expressions. Then you could use pattern matching (which I think was the original intent of your question):

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

To make this more convenient, you could define an object with factory methods to construct the regular expressions. However, due to how pattern matching works, you'll still have to define the expressions outside of the match:

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 _ =>
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文