解決策はすでに示されていますが、さらに説明が必要だと思います。
式が演算子の位置にある場合にのみ、括弧とドットを残すことができます。式が の場合、式は演算子の位置にあり<object> <method> <param>ます。これは、複数の明示的なパラメーター リストを含むメソッドの場合には当てはまりませんfoldLeft。したがって、書く必要があります<list>.foldLeft(<init>)(<function>)。それにもかかわらず、Scala にはこれを回避するための特別なルールがあります。別の括弧のセットを挿入できます: (<list> foldLeft <init>) (<function>). さらに、 と定義され/:た と同義であると呼ばれる別のメソッドがあります。それはあなたが書くことを可能にします。ここで、最初の括弧の間の記号が入れ替わっていることに気付いたかもしれません。これは、コロンで終わる各メソッドが左結合ではなく右結合であるという規則によるものです (詳細説明)。foldLeftdef /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)(<init> /: <list>) (<function>)
ここで、さらにリファクタリングするためのヒントをいくつか提供したいと思います。
Tuple2[A, B]次のように書くことができます(A, B)
- すべてのタイプを記述する必要はありません。それらのいくつかは、コードを整理するために残しておくことができます (また、残しておく必要があります) (あなたが初心者で、これを書きたいと思っていることはわかっています。ヒントとしてのみ...)。でも離れないで
xsリストはたいていorのような名前が付けられysますが、これは「たくさんの x」または「たくさんの y」を意味するためです。これはあまり重要ではありませんが、一般的です
- パラメータをパタリングして、読みやすい名前に抽出できます。
... { case (a, (b,c)) => ...}
- タスクを要求しているため、コードは機能しません。次のようなものが必要です
List.fill(<n>)(<elem>)
- リストに要素を追加しないでください。これは
O(n). :::暗黙的に追加操作です -ソースを見てください。
- このタスク
foldLeftは、思いつく最善の解決策ではありません。または、操作でコピーする必要のある要素が少ないためfoldRight、シノニムの:\方が効率的である可能性があります。:::しかし、私はflatMap(以下を参照)、map+flatten
- for-comprehension を使用してこれを解決できます。これは多くの場合、読みやすいでしょう。for-comprehensions が内部でどのように実現されるかについての詳細は、これを参照してください。
すべてのサンプルソリューションのすべて:
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")
}