我有两个Map[String, T]
,其中T
是Fruit
子类型的实例。 我需要从两个 Map 构建新 Map,其中键是两个映射中的公共键名,值是两个映射中的值共享相同类型的Seq[Fruit]
。
class Fruit
case class Apple() extends Fruit
case class Banana(num: Int) extends Fruit
case class Orange() extends Fruit
例如,如果我有以下两张地图:
val map1 = Map("first" -> Apple(),
"second" -> Banana(3),
"third" -> Orange())
val map2 = Map("first" -> Orange(),
"second" -> Banana(4),
"third" -> Orange())
我需要结果图,map3
具有以下成员:
generateMap(map1: Map[String, Fruit], map2: Map[String, Fruit]): Map[String, Seq[Fruit]]
=> results a map look like
Map("second" -> Seq(Banana(3), Banana(4)),
"third" -> Seq(Orange(), Orange())
我不确定如何编写函数,generateMap
. 谁能帮我实现这一点?(使用 Scala 2.11.x)
请注意,类定义(水果和其他)是固定的,所以我无法修改它们。
scala> val r: Map[String, Seq[Fruit]] = (map1.toList ++ map2.toList).
groupBy(x => x._1).
mapValues(lst => lst.map(x => x._2)).
.filter {
case (key, lst) => lst.forall(x =>
x.getClass == lst.head.getClass)
}
r: Map[String, Seq[Fruit]] = Map(third -> List(Orange(), Orange()),
second -> List(Banana(3), Banana(4)))
val m3 = (map1.toSeq ++ map2.toSeq). // Combine the maps
groupBy (x=>x._1). //Group by the original keys
map{case (k,lst)=> (k, lst.map(x=> x._2))}. //Strip the keys from the grouped sequences
filter{case (_, lst) => lst.forall(i => lst.head.getClass == i.getClass)}. //Filter out hetergeneous seqs
toMap // Make a map
Without forall:
(map1.toList ++ map2.toList).groupBy(_._1).mapValues(_.map(_._2))
.filter(_._2.map(_.getClass).toSet.tail.isEmpty)
Map(third -> List(Orange(), Orange()), second -> List(Banana(3), Banana(4)))
这个版本需要比forall
版本多一点(但在filter
内部仍然是线性的)CPU和内存,所以你应该只对小集合使用它。