ScalaのMap->Listで気をつけるべきこと
0から30までの数値を3つずつの組み合わせにまとめたい事案があったとします
scala> (0 to 30).groupBy(_ / 3).map(_._2).toList res207: List[scala.collection.immutable.IndexedSeq[Int]] = List( Vector(0, 1, 2), Vector(15, 16, 17), Vector(30), Vector(3, 4, 5), Vector(18, 19, 20), Vector(27,28, 29), Vector(6, 7, 8), Vector(21, 22, 23), Vector(9, 10, 11), Vector(24, 25, 26), Vector(12, 13, 14))
※適当に整形してあります
順番がめちゃくちゃじゃないか(困惑
どうしてこうなった
MapからListになる時に何かあったに違いない
scala> Map(1 -> 'a', 2 -> 'z', 4 -> 'd',3 -> 'c').toList res202: List[(Int, Char)] = List((1,a), (2,z), (4,d), (3,c))
順番がそのままになる。普通に作られるmapがsortedmap,treemapでない。明示的に扱うなら変換をかませればいいのだが。辞書型といえど(Int,Char)のIntをキーにアクセスしているだけで中身はめちゃくちゃですよとかそういう
groupByで生成されるMapは順番が保証されていない
scala> (0 to 30).groupBy(_ / 3) res204: scala.collection.immutable.Map[Int,scala.collection.immutable.IndexedSeq[Int]] = Map(0 -> Vector(0, 1, 2), 5 -> Vector(15, 16, 17), 10 -> Vector(30), 1 -> Vector(3, 4, 5), 6 -> Vector(18, 19, 20), 9 -> Vector(27, 28, 29), 2 -> Vector(6, 7, 8), 7 -> Vector(21, 22, 23), 3 -> Vector(9, 10, 11), 8 -> Vector(24, 25, 26), 4 -> Vector(12, 13, 14))
※適当に整形してあります
たいがいMap以外を暗黙に生成してるのはScala歴一ヶ月の俺でもほぼ見たことない
解決策
並び替えてくれる方に一度変換するか、sortつかえsort
できた
元はといえばdivide作りたかっただけなのに、中身にぶっこんでた値がアレな制で余計に複雑にしてしまった感がすごい
追記
groupedでできる