scala:两个变量的类型相等

时间:2015-04-17 10:21:42

标签: scala reflection types equality

我有两个Map[String, T],其中TFruit子类型的实例。我需要从两个地图构建新的地图,其中的关键是两个地图中的公共关键名称,如果两个地图中的值共享相同的类型,则值为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和其他)是固定的,因此我无法修改它们。

3 个答案:

答案 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和内存,因此您只能将它用于小型集合。