リストからインデクスをキーとしたマップを生成
まれに必要になる処理なのですが、美しく書くにはどうしたものか・・・
リストのサイズと Range を使えばもっとシンプルにかけることに気付きました。というか、気付けよ私(ase
scala> val list = List("foo", "bar", "baz")
list: List[java.lang.String] = List(foo, bar, baz)scala> val map = Map((0 to list.size).toList.zip(list): _*)
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(0 -> foo, 1 -> bar, 2 -> baz)
(0 to list.size) で、0, 1, 2, 3 の Range を作っています。3 が余分ですが zip で捨てられるので気にしない方向で。
今のところ foldLeft と zip と Map.apply をつかって書いてます。
scala> val list = List("foo", "bar", "baz")
list: List[java.lang.String] = List(foo, bar, baz)scala> val indexes = (List[Int]() /: list) { (x, y) => x match {
| case head::_ => (head+1)::x
| case _ => List(0)
| } } reverse
indexes: List[Int] = List(0, 1, 2)scala> val map = Map(indexes.zip(list): _*)
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(0 -> foo, 1 -> bar, 2 -> baz)
以下、hashCode をキーにした場合のコード例です。
scala> val map = Map(list.map(_.hashCode).zip(list): _*)
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(101574 -> foo, 97299 -> bar, 97307 -> baz)
ポイントとしては、Map.apply の引数は可変長なので、_* をつけて展開して渡しています。
通常の使用であれば Map( (0 -> "foo"), (1 -> "bar"), (2 -> "baz") ) のように、任意の個数を引数として渡すのですが、List(というか Seq) の中身を渡したい場合は _* をつける必要があります。