Reputation: 3
Having val mapList: List[Map[String, Int]]
, I want to do something like:
val map = mapList foldLeft (Map[String, Int]()) ( _ ++ _ )
or
val map = mapList foldLeft (Map[String, Int]())
( (m1: Map[String, Int], m2: Map[String, Int]) => m1 ++ m2 )
Neither option is compiled (first says "missing parameter type for expanded function (x, y) => x ++ y
" and second says "type mismatch; found (Map[String, Int], Map[String, Int]) => Map[String, Int];
required: String
").
I want to achieve a classical solution for concatenating a list of immutable maps such as List( Map("apple" -> 5, "pear" -> 7), Map("pear" -> 3, "apricot" -> 0) )
would produce a Map("apple" -> 5, "pear" -> 10, "apricot" -> 0)
.
Using scala 2.10.5
.
Upvotes: 0
Views: 256
Reputation: 16324
You need to add a dot before foldLeft
. You can only use spaces instead of dots under specialized conditions, such as for methods with exactly 1 parameter (arity-1 methods):
val map = mapList.foldLeft(Map[String, Int]()) ( _ ++ _ )
You can read more about method invocation best practices here.
You might also be interested in the reduce
methods, which are specialized versions of the fold
methods, where the return type is the same as the type of the elements of the collection. For example reduceLeft
uses the first element of the collection as a seed for the foldLeft
. Of course, since this relies on the first element's existence, it will throw an exception if the collection is empty. Since reduceLeft
takes only 1 parameter, you can more easily use a space to invoke the method:
mapList.reduceLeft( _ ++ _)
mapList reduceLeft(_ ++ _)
Finally, you should note that all you are doing here is merging the maps. When using ++
to merge the maps, you will just override keys that are already present in the map – you won't be adding the values of duplicate keys. If you wanted to do that, you could follow the answers provided here, and apply them to the foldLeft
or reduceLeft
. For example:
mapList reduceLeft { (acc, next) =>
(acc.toList ++ next.toList).groupBy(_._1).toMap.mapValues(_.map(_._2).sum)
}
Or slightly differently:
mapList.map(_.toSeq).reduceLeft(_ ++ _).groupBy(_._1).toMap.mapValues(_.map(_._2).sum)
And, if you're using Scalaz, then most concisely:
mapList reduceLeft { _ |+| _ }
Upvotes: 3