拥有val mapList: List[Map[String, Int]]
,我想做类似的事情:
val map = mapList foldLeft (Map[String, Int]()) ( _ ++ _ )
或
val map = mapList foldLeft (Map[String, Int]())
( (m1: Map[String, Int], m2: Map[String, Int]) => m1 ++ m2 )
这两个选项都没有编译(首先说“扩展函数(x, y) => x ++ y
缺少参数类型”,第二个说“类型不匹配;找到(Map[String, Int], Map[String, Int]) => Map[String, Int];
所需:String
”。
我想要实现连接不可变地图列表的经典解决方案,例如List( Map("apple" -> 5, "pear" -> 7), Map("pear" -> 3, "apricot" -> 0) )
会产生Map("apple" -> 5, "pear" -> 10, "apricot" -> 0)
。
使用scala 2.10.5
。
答案 0 :(得分:3)
您需要在foldLeft
之前添加一个点。在特殊条件下,您只能使用空格而不是点,例如对于具有1个参数(arity-1方法)的方法:
val map = mapList.foldLeft(Map[String, Int]()) ( _ ++ _ )
您可以阅读有关方法调用最佳做法的更多信息here。
您可能也对reduce
方法感兴趣,这些方法是fold
方法的专用版本,其中返回类型与集合元素的类型相同。例如,reduceLeft
使用集合的第一个元素作为foldLeft
的种子。当然,由于这依赖于第一个元素的存在,如果集合为空,它将抛出异常。由于reduceLeft
只接受1个参数,因此您可以更轻松地使用空格来调用该方法:
mapList.reduceLeft( _ ++ _)
mapList reduceLeft(_ ++ _)
最后,你应该注意到你在这里所做的只是合并地图。使用++
合并地图时,您只需覆盖地图中已存在的键 - 您将不会添加重复键的值。如果您想这样做,可以按照here提供的答案,将其应用到foldLeft
或reduceLeft
。例如:
mapList reduceLeft { (acc, next) =>
(acc.toList ++ next.toList).groupBy(_._1).toMap.mapValues(_.map(_._2).sum)
}
或略有不同:
mapList.map(_.toSeq).reduceLeft(_ ++ _).groupBy(_._1).toMap.mapValues(_.map(_._2).sum)
而且,如果您正在使用Scalaz,那么最简洁:
mapList reduceLeft { _ |+| _ }