def flatten(l: List[_]): List[_] = {
def iflatten(l: List[_], ret: List[_]): List[_] = l match {
case Nil => ret
case h :: Nil =>
if( h.isInstanceOf[List[_]]) { iflatten(h, ret) }
else {
l.head :: ret
iflatten(l.tail, ret)
}
}
}
我知道有多种方法可以做到这一点,而且我不能100%确定我的方式是正确的。我想测试一下,但我遇到的一个问题是在我调用的第二个case语句中:
... { iflatten(h, ret) }
我收到编译错误:
error: type mismatch;
found : Unit
required: List[?]
我正在尝试解决这些类型问题,以了解有关类型系统的更多信息,因为它与我过去使用的不同。关于编译器为什么抱怨的任何建议都将不胜感激。
答案 0 :(得分:9)
我没有得到与iflatten(h,ret)
相关的错误。
我得到了found : Unit; required : List[?]
错误,但是它指的是你没有调用iflatten自己扁平化:在定义之后,你需要在flatten
定义的末尾调用函数。
def flatten(l: List[_]): List[_] = {
def iflatten(l: List[_], ret: List[_]): List[_] = l match {
case Nil => ret
case (h:List[_]) :: tail => iflatten(tail,iflatten(h,ret))
case h :: tail => iflatten(tail,h::ret)
}
iflatten(l,List()).reverse
}
至于代码本身,您可以(并且应该)在匹配时验证类型。
另请注意,case h :: Nil
仅匹配1长度列表。
对于算法,您需要在其自身内部调用iflatten
(这是任意嵌套发生的地方)。
答案 1 :(得分:3)
我认为你只是错过了演员。
if( h.isInstanceOf[List[_]]) { iflatten(h.asInstanceOf[List[_]], ret) }
或者:模式匹配会更漂亮。
h match {
case hList: List[_] =>
iflatten(hList, ret)
case _ =>
l.head :: ret
iflatten(l.tail, ret)
}
(警告:这只是我的头脑,我没有通过编译器放任何东西)
编辑 - Marth将其合并到之前的模式匹配中的解决方案看起来比我的好。
答案 2 :(得分:3)
实际上,我怀疑问题在于你定义内部方法iflatten,但从不调用它,因此外部方法flatten不会返回任何内容(即默认为返回类型的Unit,与列出[_]的返回类型。
尝试添加以下内容作为外部展平方法的最后一行:
iflatten(l, Nil)
除此之外,您的代码还有其他各种问题,例如不处理所有匹配情况:您处理包含一个元素的列表 - h :: Nil
- 但不是几个元素。您可能需要h :: theRest
之类的内容,然后在某处使用theRest
- 可能作为递归调用的ret
参数。
你也使用支票h.isInstanceOf[List[_]]
(通常使用isInstanceOf
是scala中的代码异味)但是然后尝试递归地将h传递给iflatten而不将其转换为List[_]
(对于例如,在@ ChristopherMartin的回答中,虽然使用asInstanceOf
是一个更大的代码味道)。 @Marth的回答给出了一个如何避免这些显式类型检查的好例子。
答案 3 :(得分:2)
我认为这是Shapeless库擅长的东西。
答案 4 :(得分:1)
抱歉,这段代码非常复杂。我试图简化它并得到这个解决方案:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def flatten(l : List[_]) : List[_] = l flatMap {
case l1 : List[_] => flatten(l1)
case otherwise => List(otherwise)
}
// Exiting paste mode, now interpreting.
flatten: (l: List[_])List[_]
scala> flatten(List(1,2,3))
res3: List[Any] = List(1, 2, 3)
scala> flatten(List(1,2,List(3,4)))
res4: List[Any] = List(1, 2, 3, 4)
scala> flatten(List(List(1,List(2),3),4,List(4,5)))
res5: List[Any] = List(1, 2, 3, 4, 4, 5)
修复代码(添加对iflat
的调用)后,我做了以下重构:
flatMap
进行迭代(因此可以消除或简化某些case
表达式)instanceOf
我认为更简单的解决方案是使用shapeless library(提示:查找“样板”部分)。