0

I have two Map[String, T]s, where T is an instance of subtype of Fruit. I need to construct new Map from two Maps, where the key is the common key names from the two maps, and the value is the Seq[Fruit] iff the values from the two maps shares the same type.

class Fruit case class Apple() extends Fruit case class Banana(num: Int) extends Fruit case class Orange() extends Fruit 

For example, if I have following two maps:

val map1 = Map("first" -> Apple(), "second" -> Banana(3), "third" -> Orange()) val map2 = Map("first" -> Orange(), "second" -> Banana(4), "third" -> Orange()) 

I need the result map, map3 which has following members:

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()) 

I'm not sure how to write a function, generateMap. Could anyone help me to implement that? (using Scala 2.11.x)

Note that the class definitions (Fruits and others) are fixed, so I cannot modify them.

3 Answers 3

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))) 
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, but the result is different from what I expected. Because the map1("first") has the different type from map2("first"), the generated output should not have "first".
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

Comments

0

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))) 

This version requires a little more (but still linear inside filter) CPU and memory than version with forall, so you should use it only for small collections.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.