首页 > 解决方案 > scala MatchError 从模式匹配创建元组

问题描述

我写了以下代码:

case class Filters(city: List[String], isType: List[String])

val input = "BNG:school | HYD:school,restaurant"

val(filter1:Filters, filter2:Filters) = input.split("\\|") match {
  case Array(f1, f2) => (f1.split(":") match {
      case Array(c,t) => t match {
        case _ if t contains "," => Filters(List(c.trim), t.split(",").map(_.trim).toList)
        case _ => Filters(List(c.trim), List(t.trim))
      }
    },
    f2.split(":") match {
      case Array(c,t) => t match {
        case _ if t contains "," => Filters(List(c.trim), t.split(",").map(_.trim).toList)
        case _ => Filters(List(c.trim), List(t.trim))
    }
  })
  case _ => (input.split(":") match {
    case Array(x,y) => Filters(List(x.trim), List(y.trim))
  },Nil)
}

它提供以下输出:

filter1: Filters = Filters(List(BNG),List(school))
filter2: Filters = Filters(List(HYD),List(school, restaurant))

但是,如果我将输入更改为:val input = "BNG:school"

输出给出错误:

Exception in thread "main" scala.MatchError: (Filters(List(BNG),List(school)),List()) (of class scala.Tuple2)

我不知道我做错了什么?我有三种类型的输入:

BNG:school
HYD:school,restaurant
BNG:school | HYD:school,restaurant

该代码应该适用于这些类型的输入。

其次: 如果我从 filter1 和 filter2 中删除数据类型过滤器,则输出为:

filter1: Filters = Filters(List(BNG),List(school))
filter2: Product with Serializable = Filters(List(HYD),List(school, restaurant))

为什么filter1属于Filters类型,而filter2属于Product with Serializable类型?

任何帮助表示赞赏。

提前致谢。

标签: scalatuplespattern-matching

解决方案


您的代码假定input包含 2 个Filter字符串。如果它实际上包含少于 2 个或多于 2 个,那么事情就会崩溃。

这可以通过多次、多种方式拆分输入来完成。

val input = "BNG:school | HYD:school,restaurant|LND,HKG:restaurant"
input.split("\\s*\\|\\s*")
  .map { ss =>
    val Array(cs, ts) = ss.split("\\s*:\\s*")
    Filters(cs.split(",").toList, ts.split(",").toList)
  }.toList

//res0 = List(Filters(List(BNG),List(school))
//          , Filters(List(HYD),List(school, restaurant))
//          , Filters(List(LND, HKG),List(restaurant)))

或者您可以使用正则表达式模式来帮助隔离数据元素。

val re = "([^|:]+):([^|:]+)".r
re.findAllMatchIn(input)
  .map(m => Filters(m.group(1).trim.split(",").toList
                   ,m.group(2).trim.split(",").toList)).toList

这里的一大优势是正则表达式搜索将简单地跳过格式错误的数据(例如丢失:)而不是抛出错误。


则表达式模式解释:

  • [^|:]- 任何不是^意味着不是)横杠|或冒号的字符:
  • [^|:]+- 必须至少是其中的 1 个(+表示1 个或多个
  • ([^|:]+)- 记住那个组(parens 创建一个“捕获组”)
  • ([^|:]+):([^|:]+)- 2 个捕获组 ( group(1)and group(2)) 以冒号分隔:。每个组由冒号之前和之后的所有字符组成,这些字符不是竖线字符或冒号字符。

推荐阅读