2015-02-08 56 views
0

尝试创建一个方法来确定一个集是否是另一个集的子集,两者都作为参数给出。当我试图测试它时,控制台打印出来这个scala元组有什么不对?

scala.MatchError:(List(1,2,3,4,5,6,7),List(1,2,3,4))(class scala.Tuple2),

给出的两个列表是我用来测试它的参数。另外,斯卡拉让我在真假面前输入回报,任何导致这种情况的想法是什么?

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

回答

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,因为你的思考方式实际上可能导致你进入这个陷阱。早期返回的方法可能会导致错误,并且难以阅读。

一个更清晰的实现方法可以使用diff。如果b的元素组减去a的元素为空,则b可以被认为是a的子集。

def subset(a: List[Int], b: List[Int]): Boolean = (b.distinct diff a.distinct).nonEmpty 

distinct如果有可能为ab包含重复时才需要,因为我们正在尝试一种ListSet时,它实际上不是。

更好的是,如果我们将List s转换为Set s,那么我们可以使用subsetOf

def subset(a: List[Int], b: List[Int]): Boolean = b.toSet.subsetOf(a.toSet) 
+0

请注意,一个更复杂的类型系统可能会认识到只有非零的'b'的情况才能逃过第一场比赛。 – 2015-02-08 22:29:53

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

Scala的匹配表达式应该匹配到至少一个情况表达。否则会引发MatchError。

你应该使用下列情况:

(a, b) match { 
    case (_, Nil) => true 
    case (aa, h :: t) if aa contains h => subset(aa, t) 
    case _ => false 
} 
1

的另一种方法可以调用标准库的方法。

对于'b'中的每个元素,检查'a'是否包含该元素。

下面是简单的代码:

def subset(a: List[Int], b: List[Int]): Boolean = { 
    (b.forall(a.contains(_))) 
} 
+0

什么的if-else的,返回该噪声呢?只是def子集()= b.forall .... – 2015-02-08 20:36:19

+0

@JiříVypědřík你是完全正确的!更改了代码。谢谢! – 2015-02-08 20:38:57

0

只要对象不匹配模式匹配表达式的任何模式就会发生MatchError。

的另一种方法是使用dropWhiletakeWhile

def subsets(a:List[Int], b:List[Int]):Boolean = { 
return b.dropWhile { ele => a.contains(ele)}.size==0 
} 

OR

def subsets(a:List[Int], b:List[Int]):Boolean = { 
return b.takeWhile { ele => a.contains(ele)}.size==b.size 
}