尝试创建一个方法,确定一个集是否是另一个集的子集,两者都作为参数给出。当我试图测试时,控制台打印出来
scala.MatchError :(列表(1,2,3,4,5,6,7),列表(1,2,3,4))(类scala.Tuple2),
给出的两个列表是我用作测试它的参数。另外,scala让我在真假之前输入回复,任何想法导致了这一点吗?
def subset(a: List[Int], b: List[Int]): Boolean ={
(a,b) match {
case (_,Nil)=> return true
}
b match {
case h::t if (a.contains(h)) => subset(a,t)
case h::t => return false
}}
答案 0 :(得分:5)
其他答案并不能完全回答为什么您的代码不正确。当列表b
为空且非空并且一切都应该没问题时,您似乎正在处理此案例,但事实上您实际上并非如此。让我们再次查看您的代码,并修复一些格式。
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => return true
} // we can never make it past here, because either we return true,
// or a MatchError is raised.
b match {
case h :: t if (a.contains(h)) => subset(a,t)
case h :: t => return false
}
}
这里真正的问题是你有两个完全断开的match
语句。因此,当b
非空时,第一个匹配将失败,因为它仅处理b
为Nil
时的情况。
正如其他解决方案所指出的,正确的方法是将两个match
语句合并为一个。
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, Nil) => true
case (xs, head :: tail) if(xs contains head) => subset(xs, tail)
case _ => false
}
}
请注意不再需要return
语句。在scala中,您应该尽可能避免使用return
,因为您在return
周围的思考方式可能会导致您陷入此陷阱。早期返回的方法可能会导致错误,并且难以阅读。
实现这一目标的更简洁方法可以使用diff
。如果b
的元素集合减去a
的元素为空,则可以将b
视为a
的子集。
def subset(a: List[Int], b: List[Int]): Boolean = (b.distinct diff a.distinct).nonEmpty
仅当distinct
和a
包含重复项时才需要 b
,因为我们正在尝试像List
一样Set
{1}}当它实际上没有。
更好的是,如果我们将List
转换为Set
s,那么我们就可以使用subsetOf
。
def subset(a: List[Int], b: List[Int]): Boolean = b.toSet.subsetOf(a.toSet)
答案 1 :(得分:1)
Scala匹配表达式应与至少一个案例表达式匹配。否则会引发MatchError。
您应该使用以下案例:
(a, b) match {
case (_, Nil) => true
case (aa, h :: t) if aa contains h => subset(aa, t)
case _ => false
}
答案 2 :(得分:1)
另一种方法是调用标准库中的方法。
对于'b'中的每个元素,检查'a'是否包含该元素。
以下是简单的代码:
def subset(a: List[Int], b: List[Int]): Boolean = {
(b.forall(a.contains(_)))
}
答案 3 :(得分:0)
MatchError - This class implements errors which are thrown whenever an object doesn't match any pattern of a pattern matching expression.
显然,其中包含元素的第二个列表将导致此错误,因为没有模式匹配。您应该像第一个match
那样添加另一个分支:
def subset(a: List[Int], b: List[Int]): Boolean = {
(a, b) match {
case (_, List()) => return true
case _ => b match {
case h :: t if (a.contains(h)) => subset(a, t)
case h :: t => return false
}
}
}