0

I found this method:

def merge[K, V](maps: Seq[Map[K, V]])(f: (K, V, V) => V): Map[K, V] = {
      maps.foldLeft(Map.empty[K, V]) { case (merged, m) =>
        m.foldLeft(merged) { case (acc, (k, v)) =>
          acc.get(k) match {
            case Some(existing) => acc.updated(k, f(k, existing, v))
            case None => acc.updated(k, v)
          }
        }
      }
    }

but it gives me a type mismatch error if i use it like this:

val mergeMsg = (map1: LinkedHashMap[Int, ListBuffer[Int]], map2: LinkedHashMap[Int, ListBuffer[Int]]) =>
    {
      val ms=Seq(map1, map2)
      merge(ms.map(_.mapValues(List(_)))){(_, v1, v2) => v1 ++ v2}
    }

The error says: "Type mismatch, expected: mutable.Seq[Mutable.Map[NotInferedK, NotInferedV]], actual: mutable.Seq[Map[Int, List[ListBuffer[Int]]]]"

How can i solve this? I know it's something simple, but i'm new to scala.

Andrea
  • 47
  • 7

2 Answers2

1

The problem is that you are passing in to merge a sequence of mutable LinkedHashMaps. The function requires a sequence of immutable Maps.

You need to convert your LinkedHashMaps to the correct type first. The simplest way to do this is probably to call .toMap before you perform the mapValues.

merge(ms.map(_.toMap.mapValues(List(_)))){(_, v1, v2) => v1 ++ v2}

Update

Alternatively the method signature for Merge can be change to explicitly use scala.collection.Map. It will, by default, use scala.collection.immutable.Map.

def merge[K, V](maps: Seq[scala.collection.Map[K, V]])(f: (K, V, V) => V): scala.collection.Map[K, V]
Chris C
  • 229
  • 2
  • 3
  • `LinkedHashMap` extends `scala.collection.mutable.Map` which extends `scala.collection.Map`, doesn't it? – SergGr Dec 02 '17 at 15:01
  • True, but I believe your method signature `...Seq[Map[K, V]]...` will default to using `scala.collection.immutable.Map` (unless you have specifically imported `scala.collection.Map`). You can make this explicit in the signature of merge using something like `def merge[K, V](maps: Seq[scala.collection.Map[K, V]])(f: (K, V, V) => V): scala.collection.Map[K, V]` - which should mean that your original code compiles. – Chris C Dec 02 '17 at 15:12
  • Thank you, it solved the mismatch, but now it cannot resolve the ++ symbol. – Andrea Dec 02 '17 at 15:47
  • Please could you post your `merge` method signature and your `mergeMsg` function? – Chris C Dec 02 '17 at 16:02
  • Now i have `def merge[K, V](maps: Seq[scala.collection.Map[K, V]])(f: (K, V, V) => V): scala.collection.Map[K, V]`. The `mergeMsg` function is not changed. – Andrea Dec 02 '17 at 16:27
  • The `mergeMsg` function should be fine if `merge` has that method signature. This is working for me: `val mergeMsg = (map1: mutable.LinkedHashMap[Int, ListBuffer[Int]], map2: mutable.LinkedHashMap[Int, ListBuffer[Int]]) => { val ms = Seq(map1, map2) merge(ms.map(_.mapValues(List(_)))) { (_, v1, v2) => v1 ++ v2 } }`. Check the parentheses are in the correct place... – Chris C Dec 02 '17 at 16:51
  • I don't know, parentheses are ok.. I really appreciate your help btw, thank you. – Andrea Dec 02 '17 at 17:07
  • I'm on this again. The `merge` method merges my LinkedHashMaps into a Map, and i don't want that, I need another LinkedHashMap. What should i change of it? – Andrea Dec 05 '17 at 08:13
0
val mergeMsg = (map1: LinkedHashMap[Int, ListBuffer[Int]], 
                map2: LinkedHashMap[Int, ListBuffer[Int]]) => {
      val ms = Seq (map1.toMap, map2.toMap)
      merge (ms) ((_, lb1, lb2) => (lb1 ++ lb2))
 }

So the Type needs just to be converted to Map. The k is not used for the process of updating, so we use _ instead. The lbs are for ListBuffers.

user unknown
  • 35,537
  • 11
  • 75
  • 121