解决方案已经给出,但我认为需要更多解释:
如果您的表达式位于操作符位置,您只能留下括号和点。如果表达式的形式为 ,则表达式处于操作符位置<object> <method> <param>
。对于包含多个显式参数列表的方法,情况并非如此foldLeft
。因此,您必须编写<list>.foldLeft(<init>)(<function>)
. 尽管如此,Scala 有一个特殊的规则来解决这个问题——你可以插入另一组括号:(<list> foldLeft <init>) (<function>)
. 此外,还有另一种称为 的方法/:
,它是 的同义词foldLeft
,定义为def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)
。它允许您编写(<init> /: <list>) (<function>)
. 也许你刚刚注意到这里第一个括号之间的符号被交换了——这是因为每个以冒号结尾的方法都是右关联的而不是左关联的(进一步解释)。
现在我想给你一些进一步重构的提示:
Tuple2[A, B]
可以写成(A, B)
- 您不必编写所有类型。其中一些可以 - 并且应该 - 留下来清理你的代码(我知道你是一个初学者并且想写这个。只是作为一个提示......)。但不要离开
- 列表大多被命名为
xs
或ys
,因为这意味着“很多 x”或“很多 y”。这不是很重要但很常见
- 您可以对参数进行模式匹配以将它们提取为易于阅读的名称:
... { case (a, (b,c)) => ...}
- 您的代码在声明任务时不起作用。你需要类似的东西
List.fill(<n>)(<elem>)
- 不要将元素附加到列表中,这是
O(n)
. :::
隐含地是一个追加操作 - 查看源代码。
- 对于这个任务
foldLeft
来说不是最好的解决方案。foldRight
或者同义词:\
可能更有效,因为该:::
操作需要更少的元素来复制。但我更喜欢flatMap
(见下文),这是一个map+flatten
- 您可以使用 for-comprehension 来解决这个问题,这通常很容易阅读。有关如何在内部实现理解的更多信息,请参阅此内容。
总而言之,示例解决方案:
object Test extends App {
def decode1(l: List[Tuple2[Int, Symbol]]): List[Symbol] =
l.foldLeft(List[Symbol]()) { (symbols: List[Symbol], e: Tuple2[Int, Symbol]) => symbols ::: List.fill(e._1)(e._2) }
def decode2(xs: List[(Int, Symbol)]): List[Symbol] =
(xs foldLeft List.empty[Symbol]) { case (xs, (n, s)) => xs ::: List.fill(n)(s) }
def decode3(xs: List[(Int, Symbol)]): List[Symbol] =
(xs foldRight List.empty[Symbol]) { case ((n, s), xs) => List.fill(n)(s) ::: xs }
def decode4(xs: List[(Int, Symbol)]): List[Symbol] =
(List.empty[Symbol] /: xs) { case (xs, (n, s)) => xs ::: List.fill(n)(s) }
def decode5(xs: List[(Int, Symbol)]): List[Symbol] =
xs flatMap { case (n, s) => List.fill(n)(s) }
def decode6(xs: List[(Int, Symbol)]): List[Symbol] =
for {
(n, s) <- xs
ys <- List.fill(n)(s)
} yield ys
val xs = List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e))
val ys = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
println("start testing")
val tests = List[List[(Int, Symbol)] => List[Symbol]](decode1, decode2, decode3, decode4, decode5, decode6)
for (t <- tests)
assert(t(xs) == ys)
println("finished")
}