在 Scala 中,调用groupBy()
一个集合返回一个Map
值是集合的地方,但我想要一个MultiMap
. 进行转换的最简单方法是什么?我可以避免创建一个新的MultiMap
并复制所有内容吗?
问问题
540 次
1 回答
5
我认为“我必须创建一个新对象来混合 Scala 特征吗?”的答案?是是的”。您可以通过包装对象和隐式转换来最大程度地减少痛苦。
对于您的具体问题,我无法强制 groupBy(...) 将可变映射返回到可变集,您需要将其包装为“带有 MultiMap 的 MapProxy”。但是,实现您自己的“groupBy”版本并不需要太多代码行:
package blevins.example
object App extends Application {
implicit def multiMapable[B](c: Iterable[B]) = new {
def groupByMM[A](f: B => A) = {
import scala.collection.mutable._
val ret = new HashMap[A,Set[B]] with MultiMap[A,B]
for (e <- c) { ret.addBinding(f(e), e) }
ret
}
}
val c = List(1,2,3,4,5,6,7,8,9)
val mm = c.groupByMM { i => if (i < 5) "alpha" else "beta" }
mm.addBinding("alpha",12)
println(mm) // Map(beta -> Set(5, 7, 6, 9, 8), alpha -> Set(3, 1, 4, 2, 12))
}
附录
这是一个将现有 Map[String,Set[Int]] 包装到 MultiMap 中而不复制值的示例:
object App extends Application {
import scala.collection.mutable._
val seed: Map[String,Set[Int]] = Map("even" -> Set(2,4,6), "odd" -> Set(1,3,5))
val multiMap = new MapProxy[String,Set[Int]] with MultiMap[String,Int] {
val self = seed
}
multiMap.addBinding("even", 8)
println(multiMap) // Map(odd -> Set(5, 3, 1), even -> Set(6, 8, 4, 2))
}
请注意,这不能在 groupBy(...) 的结果上完成,因为种子映射需要是可变的并且 groupBy(...) 返回一个不可变映射。
于 2009-11-27T23:11:50.793 回答