這是類似於this question。基本上,正如@serejja所說,你的方法是正確的,也是最簡潔的方法。你可以使用collection.breakOut
作爲生成器工廠的說法到最後map
,從而節省額外的迭代,以獲得Set
類型:
l.groupBy(_._2).mapValues(_.map(_._1)(collection.breakOut): Set[Int])
你不應該可能超越這個,除非你真的需要擠壓性能。
否則,這是一般toMultiMap
功能可能看起來怎麼樣,它允許你控制值的集合類型:
import collection.generic.CanBuildFrom
import collection.mutable
def toMultiMap[A, K, V, Values](xs: TraversableOnce[A])
(key: A => K)(value: A => V)
(implicit cbfv: CanBuildFrom[Nothing, V, Values]): Map[K, Values] = {
val b = mutable.Map.empty[K, mutable.Builder[V, Values]]
xs.foreach { elem =>
b.getOrElseUpdate(key(elem), cbfv()) += value(elem)
}
b.map { case (k, vb) => (k, vb.result()) } (collection.breakOut)
}
它是什麼,它在創建階段期間使用可變地圖,並且首先收集的值可變爲Builder
(構建器由CanBuildFrom
實例提供)。對所有輸入元素的迭代完成後,構建器值的可變映射將轉換爲值集合類型的不可變映射(再次使用collection.breakOut
技巧來立即獲取所需的輸出集合)。
例:
val l = List((1,2,3),(4,2,5),(2,3,3),(10,3,2))
val v = toMultiMap(l)(_._2)(_._1) // uses Vector for values
val s: Map[Int, Set[Int] = toMultiMap(l)(_._2)(_._1) // uses Set for values
所以註釋的結果類型指示值類型的類型推斷。如果你不註釋結果,Scala會選擇Vector
作爲默認的集合類型。
我認爲你的解決方案很好 – serejja