flatMap は、二重のリストの内側のリストを map して、結果をフラットなリストにするメソッドだ。
Ruby で書くとこう。
irb(main):001:0> [[1,2,3], [4,5]].map{|x| x.map{|y| y * y } }.flatten => [1, 4, 9, 16, 25]
この、外側の map と flatten をいっぺんにできる。
scala> List(List(1,2,3), List(4,5)).flatMap(x => x.map(y => y * y)) res0: List[Int] = List(1, 4, 9, 16, 25)
さらに、ちょっと工夫すると面白い使い方ができる。
scala> List(1,2,3).flatMap(x => List(10,20).map(y => x + y)) res1: List[Int] = List(11, 21, 12, 22, 13, 23)
外側のリスト List(1,2,3) と内側に現れるリスト List(10,20) とで、あたかも二十ループのようになっている。実際これはつぎの for-comprehension と同じだ。
scala> for (x <- List(1,2,3); y <- List(10,20)) yield x + y res1: List[Int] = List(11, 21, 12, 22, 13, 23)
というよりも、for-comprehension というのは上の flatMap のシンタックスシュガーなのだそうだ。
じゃぁ、三重のループもできるんだろうか。
scala> List(1,2,3).flatMap(x => List(10,20).flatMap(y => List(100,200).map(z => x + y + z))) res3: List[Int] = List(111, 211, 121, 221, 112, 212, 122, 222, 113, 213, 123, 223)
できた。
でも for で書いたほうがわかりやすいかな。