这个scala元组有什么问题?

时间:2015-02-08 20:09:32

标签: scala

尝试创建一个方法,确定一个集是否是另一个集的子集,两者都作为参数给出。当我试图测试时,控制台打印出来

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

4 个答案:

答案 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非空时,第一个匹配将失败,因为它仅处理bNil时的情况。

正如其他解决方案所指出的,正确的方法是将两个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
仅当distincta包含重复项时才需要

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