scala MatchError 从模式匹配创建元组
scala MatchError in creating tuple from Pattern Matching
我写了下面的代码:
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 中删除数据类型 Filters
它给出的输出为:
filter1: Filters = Filters(List(BNG),List(school))
filter2: Product with Serializable = Filters(List(HYD),List(school, restaurant))
为什么 filter1 是 Filters 类型而 filter2 是 Serializable 类型的产品?
感谢任何帮助。
提前致谢。
正如评论者所说,这是因为您在等式的左侧有一个元组。
也许下面的内容更好?
case class Filters(city: List[String], isType: List[String])
val regex = "(\w+):([,\w]+)".r
val input = "BNG:school | HYD:school,restaurant"
val result = input.split("\|").map(regex.findFirstMatchIn).map {
case Some(m) => Filters(List(m.group(1)), m.group(2).split(",").toList)
case None => throw new Exception("No match")
}
println(result) // Array(Filters(List("BNG"), List("school")), Filters(List("HYD"), List("school", "restaurant")))
在匹配块中使用 if-guards 时,还要注意 2.12 上的 https://github.com/scala/bug/issues/5365。
您的代码假设 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
这里的一大优势是正则表达式搜索将简单地跳过格式错误的数据(例如丢失的 :
)而不是抛出错误。
regex 模式解释:
[^|:]
- 任何 not 的字符(^
表示 not)一个小节 |
或冒号 :
[^|:]+
- 必须至少是其中的 1 个(+
表示 1-or-more)
([^|:]+)
- 记住那个组(parens 创建一个“捕获组”)
([^|:]+):([^|:]+)
- 2 个捕获组(group(1)
和 group(2)
)由冒号 :
分隔。每组由冒号前后的所有字符组成,这些字符不是条形码或冒号字符。
我写了下面的代码:
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 中删除数据类型 Filters 它给出的输出为:
filter1: Filters = Filters(List(BNG),List(school))
filter2: Product with Serializable = Filters(List(HYD),List(school, restaurant))
为什么 filter1 是 Filters 类型而 filter2 是 Serializable 类型的产品?
感谢任何帮助。
提前致谢。
正如评论者所说,这是因为您在等式的左侧有一个元组。
也许下面的内容更好?
case class Filters(city: List[String], isType: List[String])
val regex = "(\w+):([,\w]+)".r
val input = "BNG:school | HYD:school,restaurant"
val result = input.split("\|").map(regex.findFirstMatchIn).map {
case Some(m) => Filters(List(m.group(1)), m.group(2).split(",").toList)
case None => throw new Exception("No match")
}
println(result) // Array(Filters(List("BNG"), List("school")), Filters(List("HYD"), List("school", "restaurant")))
在匹配块中使用 if-guards 时,还要注意 2.12 上的 https://github.com/scala/bug/issues/5365。
您的代码假设 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
这里的一大优势是正则表达式搜索将简单地跳过格式错误的数据(例如丢失的 :
)而不是抛出错误。
regex 模式解释:
[^|:]
- 任何 not 的字符(^
表示 not)一个小节|
或冒号:
[^|:]+
- 必须至少是其中的 1 个(+
表示 1-or-more)([^|:]+)
- 记住那个组(parens 创建一个“捕获组”)([^|:]+):([^|:]+)
- 2 个捕获组(group(1)
和group(2)
)由冒号:
分隔。每组由冒号前后的所有字符组成,这些字符不是条形码或冒号字符。