解释为什么encode方法返回空Vector

时间:2018-03-24 15:16:20

标签: scala

我希望此代码返回Seq(List(a,2), List((a,2),(e,1)), List((a,2),(e,1),(t,1))),但它会返回一个空的Vector

val ws: List[(Char,Int)] = List((a,2), (e,1), (t,1))

def encode(ws: List[(Char,Int)]): Seq[List[(Char,Int)]] =
  for {
    split <- (1 to ws.length)
    wst <- ws.take(split)
    wdt <- encode(ws.drop(split))
  } yield wst::wdt

为什么返回空Vector?当我单独尝试语句wst <- ws.take(split)时,结果为List((a,2))

1 个答案:

答案 0 :(得分:2)

产生所需输出的快速一行

你真正想要的似乎是:

println(ws.inits.toList.reverse.tail)
// output:
// List(List((a,2)), List((a,2), (e,1)), List((a,2), (e,1), (t,1)))

为什么要清空Vector?

在这种或那种方式中,参数ws的长度在递归调用期间减少(因为在递归调用encode之前至少删除了一个元素)。

一旦ws的长度达到零,ws.take - 生成器就会变空,因此您的for - 表达式变为 基本上

(1 to someNumber).flatMap(_ => Nil)

由于Range在映射/ flatMapping之后产生Vector,因此您获得一个空Vector(),然后返回。

长递归解决方案

如果您(无论出于何种原因)坚持使用递归,您可以执行以下操作:

val ws: List[(Char,Int)] = List(('a',2), ('e',1), ('t',1))

def encode(ws: List[(Char,Int)]): Seq[List[(Char,Int)]] =
  if (ws.isEmpty) {
    Nil
  } else {
    encode(ws.dropRight(1)) ++ List(ws)
  }

println(encode(ws))
// output:
// List(List((a,2)), List((a,2), (e,1)), List((a,2), (e,1), (t,1)))

正确的递归通常应该是这样的:你分别处理Nil - case和非空列表情况,而不是依赖于用尽迭代的奇怪的flatMap上。

请注意,此解决方案效率不高,创建辅助方法并反转输入可能会更好。