【リベンジ】P07 Flatten a nested list structure.
前回どうしても解けなかったP07にリベンジした。今回は「ネストしたList構造を一つのListにまとめる」のを
- 再帰
- flatmap
どちらでも実装するのが目標。
1. 再帰のパターン
結局自力では分からなかった。
自力でなんとか書いたコード
myAnswer
def flatten (result: List[Any], ls: List[Any]): List[Any] = ls match {
case ls::tail if ls == classOf[List[Any]] => {
flatten(result, ls[Any])
flatten(result, tail)
}
case h::tail => {
flatten(result:+h, tail)
}
case Nil => result
case _ => throw new NoSuchElementException
}
そして当然のように動かない。
Error:(11, 27) value ls of type Any does not take type parameters.
flatten(result, ls[Any])
^
って言われる。
型パラメータの指定方法を学んだ後のコード
結局分からなかったので、S-99: Ninety-Nine Scala Problems所感 リスト操作編 - Soleil cou coupé を見てお勉強。
scala
case (xs : List[_]) :: (ys : List[_]) => flatten(xs) ::: flatten(ys)
ああー…そんなことできるのか…。
前のエラーは、resultは型パラメータを取らないよって叱られてたから、受け取るresult自体をList[Any]に限定してやれば良かったみたいだ。
と思って直したが
myAnswer
def flatten (result: List[Any], ls: List[Any]): List[Any] = ls match {
case (ls:List[Any])::(tail:List[Any]) => {
flatten(result, ls)
flatten(result, tail)
}
case h::tail => {
flatten(result:+h, tail)
}
case Nil => result
case _ => throw new NoSuchElementException
}
↓
//上記コードはmyAnswerのメソッド内メソッド
println(myAnswer(List(List(1,1),2,List(3,List(5,8)))))
↓
List(2)
Process finished with exit code 0
動かない。
普通にロジックがおかしかった
そういやresult
の扱いがおかしいわ。
じゃあこうか。
myAnswer
def flatten (result: List[Any], ls: List[Any]): List[Any] = ls match {
case (ls:List[Any])::(tail:List[Any]) => {
flatten(result, ls):::flatten(result, tail)
}
case h::tail => {
flatten(result:+h, tail)
}
case Nil => result
case _ => throw new NoSuchElementException
}
↓
List(1, 1, 2, 3, 5, 8, 2, 3, 2)
Process finished with exit code 0
うーん。だいぶ近くなっては来たけど…
パターンマッチがまだおかしい。
降参して回答例を見た。
Flatten a list - Rosetta Code
RosettaCode
def flatList(l: List[_]): List[Any] = l match {
case Nil => Nil
case (head: List[_]) :: tail => flatList(head) ::: flatList(tail)
case head :: tail => head :: flatList(tail)
}
自分のものと違うのは、与えられたListが「ListとListの結合」という場合がないことと、結果を入れようと思って設定したresult
がないこと。
美しい再帰を書く道のりは長い…。