非周期的な可変データ構造でできることはすべて、不変データ構造でもできます。トリックは非常に簡単です:
loop -> recursion or fold
mutating operation -> new-copy-with-change-made operation
したがって、たとえば、あなたのケースでは、おそらく をループして、Iterable
毎回値を追加しています。便利なトリックを適用すると、
def mkMap[K,V](data: Iterable[(K,V)]): Map[K, Iterable[V]] = {
@annotation.tailrec def mkMapInner(
data: Iterator[(K,V)],
map: Map[K,Vector[V]] = Map.empty[K,Vector[V]]
): Map[K,Vector[V]] = {
if (data.hasNext) {
val (k,v) = data.next
mkMapInner(data, map + (k -> map.get(k).map(_ :+ v).getOrElse(Vector(v))))
}
else map
}
mkMapInner(data.iterator)
}
ここでは、再帰的な内部メソッドを宣言することによってループ置換を実装することを選択しました (@annotation.tailrec を使用して、再帰が while ループに最適化されていることを確認し、スタックが壊れないようにします)。
テストしてみましょう:
val pairs = Iterable((1,"flounder"),(2,"salmon"),(1,"halibut"))
scala> mkMap(pairs)
res2: Map[Int,Iterable[java.lang.String]] =
Map(1 -> Vector(flounder, halibut), 2 -> Vector(salmon))
さて、Scala のコレクション ライブラリにも、これに役立つものが含まれていることがわかりました。
scala> pairs.groupBy(_._1).mapValues{ _.map{_._2 } }
がgroupBy
主要なメソッドであり、残りはそれが生成するものを必要な形にクリーンアップします。