我有两个Map[String, T]
,其中T
是Fruit
子类型的实例。我需要从两个地图构建新的地图,其中的关键是两个地图中的公共关键名称,如果两个地图中的值共享相同的类型,则值为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)
请注意,类定义(Fruits和其他)是固定的,因此我无法修改它们。
答案 0 :(得分:1)
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)))
答案 1 :(得分:0)
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
答案 2 :(得分:0)
没有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)))
此版本需要比filter
版本更多(但在forall
内部仍然是线性的)CPU和内存,因此您只能将它用于小型集合。