Scala:两个变量的类型相等



我有两个Map[String, T],其中TFruit子类型的实例。 我需要从两个 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和内存,所以你应该只对小集合使用它。

最新更新