2

私は自分でScalaを学んでいますが、私が書いた小さなテストアプリケーションの1つが、期待どおりに機能していません。誰かが私のテストアプリケーションが失敗する理由を理解するのを手伝ってくれませんか。

私の小さなテストアプリケーションは、次の「解凍」を行う「解凍」メソッドで構成されています

  val testList = List(Tuple2(4, 'a'), Tuple2(1, 'b'), Tuple2(2, 'c'), Tuple2(2, 'a'), Tuple2(1, 'd'), Tuple2(4, 'e'))
  require(decompress(testList) == List('a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e'))

言い換えると、Tuple2オブジェクトは、より冗長な形式に「解凍」する必要があります。しかし、メソッドから返されるのはList('a'、'a'、'a'、'a')だけです。padToステートメントは最初のTuple2で機能しますが、突然機能しなくなりますか?ただし、forループを使用して要素ごとにパディングを行うと、すべてが機能します...?

完全なコード:

object P12 extends App {

  def decompress(tList: List[Tuple2[Int,Any]]): List[Any] = {
    val startingList: List[Any] = List();
    val newList = tList.foldLeft(startingList)((b,a) => {
      val padCount = a._1;
      val padElement = a._2;

      println
      println("  Current list: " + b)
      println("  Current padCount: " + padCount)
      println("  Current padElement: " + padElement)
      println("  Padded using padTo: " + b.padTo(padCount, padElement))
      println

      // This doesn't work
      b.padTo(padCount, padElement)

//      // This works, yay
//      var tmpNewList = b;
//      for (i <- 1 to padCount)
//        tmpNewList = tmpNewList :+ padElement
//      tmpNewList
    })
    newList
  }

  val testList = List(Tuple2(4, 'a'), Tuple2(1, 'b'), Tuple2(2, 'c'), Tuple2(2, 'a'), Tuple2(1, 'd'), Tuple2(4, 'e'))
  require(decompress(testList) == List('a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e'))
  println("Everything is okay!")
}

助けていただければ幸いです-Scalaを学ぶことは、私の現在のScalaの知識では、この問題を自分で理解することはできません。

4

3 に答える 3

1

次のように解凍できます。

val list = List(Tuple2(4, 'a'), Tuple2(1, 'b'), Tuple2(2, 'c'), Tuple2(2, 'a'), Tuple2(1, 'd'), Tuple2(4, 'e'))
list.flatMap{case (times, value) => Seq.fill(times)(value)}
于 2013-03-12T20:36:25.027 に答える
1

問題は、padTo が実際に指定されたサイズまでリストを埋めることです。したがって、最初は4つの要素が埋め込まれて機能しますが、次回は現在のリストの実際の長さを追加する必要があります-したがって:

def decompress(tList: List[Tuple2[Int,Any]]): List[Any] = {
  val newList = tList.foldLeft(List[Any]())((b,a) => {
   b.padTo(a._1+b.length, a._2)
 }) 
 newList
}
于 2013-03-12T20:43:51.853 に答える
0

これは機能します:

scala> testList.foldLeft(List[Char]()){ case (xs, (count, elem)) => xs ++ List(elem).padTo(count, elem)}
res7: List[Char] = List(a, a, a, a, b, c, c, a, a, d, e, e, e, e)

実際の問題は、要素を埋めるためにb.padTo(padCount, padElement)常に同じリスト ( ) を使用すると言う場合です。b最初のタプル データがほとんどの要素を生成するため、 の次のステップでは何も追加されませんfoldLeft。2 番目のタプル データを変更すると、変更が表示されます。

scala> val testList = List(Tuple2(3, 'a'), Tuple2(4, 'b'))
testList: List[(Int, Char)] = List((3,a), (4,b))

scala> testList.foldLeft(List[Char]()){ case (xs, (count, elem)) => xs.padTo(count, elem)}
res11: List[Char] = List(a, a, a, b)

代わりに、要素を生成するためにfoldLeft使用することもできます:flatMap

scala> testList flatMap { case (count, elem) => List(elem).padTo(count, elem) }
res8: List[Char] = List(a, a, a, a, b, c, c, a, a, d, e, e, e, e)

ちなみに、Tuple(3, 'a')書くことができます(3, 'a')または3 -> 'a'

padToカウントが 0 以下のデータがある場合、期待どおりに動作しないことに注意してください。

scala> List(0 -> 'a') flatMap { case (count, elem) => List(elem).padTo(count, elem) }
res31: List[Char] = List(a)

したがって、Garret Hall が言及したソリューションを使用します。

def decompress[A](xs: Seq[(Int, A)]) =
  xs flatMap { case (count, elem) => Seq.fill(count)(elem) }

scala> decompress(List(2 -> 'a', 3 -> 'b', 2 -> 'c', 0 -> 'd'))
res34: Seq[Char] = List(a, a, b, b, b, c, c)

scala> decompress(List(2 -> 0, 3 -> 1, 2 -> 2))
res35: Seq[Int] = List(0, 0, 1, 1, 1, 2, 2)

常に正しい型を返すには、ジェネリック型シグネチャの使用を参照する必要があります。

于 2013-03-12T20:36:00.707 に答える