3

S-99: Ninety-Nine Scala Problemsの問題 12 を解決しようとしています。

問題 P10 で指定されているように生成されたランレングス コード リストを指定して、その圧縮されていないバージョンを構築します。例:

scala> decode(List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e)))
res0: List[Symbol] = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)

リスト内の要素をパターン一致させ、for ループを使用して char を連結しようとしましたが、5 行目で次のコンパイル エラーが発生しました。

type mismatch;  found   : scala.collection.immutable.IndexedSeq[List[A]]  required: List[A]

1 def decode[A](xs: List[(Int, A)]) : List[A] = xs match {
2     case Nil => Nil
3     case x :: xs => {
4                    for {
5                       i <- 1 to x._1
6                    }  yield (x._2) :: decode(xs)
7                   }
8 }

申し訳ありませんが、Scala を始めます。なぜこれが起こっているのか、それを解決する方法を誰かが説明できますか?

4

5 に答える 5

4

あなたはかなり近づいています - いくつかの問題があります。これが私が思いついた修正バージョンです:

def decode[A](xs: List[(Int, A)]) : List[A] = xs match {
   case Nil => Nil
   case x :: xs => (for {
                       i <- 1 to x._1
                    } yield (x._2)).toList ::: decode(xs)
}

最初の (おそらく最も重要な) ことは、 for-yield を囲む余分な括弧です。(x._2) :: decode(xs)これがないと、ただではなく、yield しようとしています(x._2)(それを補うために、{}ケース全体を省略できます)。

次に、for-yield の結果が List ではなく IndexedSeq になるため、List への変換を強制しました (これはさまざまな方法で処理できますが、これは単に最も適切な方法でした)。

最後に、結果のリストに連結するには、 (サブリストではなく単一のエントリを先頭に追加する) ではなくdecode(xs):::演算子 ( を使用することもできます) が必要です。++::

于 2013-10-28T22:23:36.010 に答える
4

主な問題は、リストの連結に使用する演算子です::。単一の要素をリストの先頭に追加するためだけに使用されるため、コードでは、yield (それ自体がシーケンス) の結果を aList[A]および get 型に追加しようとしています。その結果、互換性がなくなります。これは機能する修正版です - ++:2 つのシーケンスを結合するために使用できる演算子を使用します。また、別のステートメントに移動しyieldました。そうしないと、yield の周りに括弧が必要になり、各要素ではなく++:、の完全な結果で機能しyieldます (型が一致しないためにコンパイルされません)。

def decode[A](xs: List[(Int, A)]) : List[A] = xs match {
  case Nil => Nil
  case x :: xs => {
    val repeatedElems = for {
      i <- 1 to x._1
    }  yield (x._2)
    repeatedElems ++: decode(xs)
  }
}
于 2013-10-28T22:29:38.280 に答える