首页 > 解决方案 > 是否可以在 Scala 中使用模式匹配来复制“exists”方法的行为?

问题描述

假设我有一个Seq(1, 2, 3, 4, 5)并且我想知道其中是否存在值“4”。我想知道是否可以仅使用模式匹配找到并提取答案。

Seq(1, 2, 3, 4, 5) match {
  case Seq(_, 4, _*) => true
  case _ => false
}

像这样的 match 子句只有在我们指定值的位置已知时才有效。我很想知道是否可以在 Scala 中执行此操作,我是 Scala 新手,并不完全熟悉它的语法和功能。

显然使用 if gaurd 没有帮助,因为它不允许将值提取到变量中。

您可能会问为什么它甚至很重要,为什么不使用当前现有的existsfilter方法。想象一下下面的情况。

case class Score(eventName: String, amount: Integer)
case class Person(name: String, scores: Seq[Score])

假设我有一个Persons 集合,我想找到某个事件的最高分。一个人可能有该事件的分数,也可能没有。

persons.collect({
          case x @ _ if x.scores.exists(_.eventName == "event1") =>
            x.scores.find(_.eventName == "event1").get.amount
        }).max

问题是过滤器eventName被处理了两次。
我知道可以使用多次迭代filter来做到这一点。map但我很想知道是否有使用模式匹配的解决方案,通过模式匹配,您可以同时找到并将值提取到变量中。

标签: scalapattern-matching

解决方案


您可以使用以下方法编写自定义匹配器unapply

case class EventScore(eventName: String) {
  def unapply(person: Person): Option[Int] =
    person.scores.collectFirst { case s if s.eventName == eventName => s.amount }
}

val score = EventScore("event1")

persons.collect({
  case score(amount) => amount
}).max

推荐阅读