2015-07-10 107 views
0

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

回答

3

您需要在foldLeft之前添加一个点。你可以只用空格代替点专业的条件下,如用正好1参数(参数数量-1的方法)方法:

val map = mapList.foldLeft(Map[String, Int]()) (_ ++ _) 

你可以阅读更多关于方法调用的最佳实践here

您可能还对reduce方法感兴趣,它们是fold方法的专用版本,其中返回类型与集合元素的类型相同。例如reduceLeft使用集合的第一个元素作为foldLeft的种子。当然,因为这依赖于第一个元素的存在,所以如果集合是空的,它将抛出异常。由于reduceLeft只需要1个参数,就可以更方便地使用空间要调用的方法:

mapList.reduceLeft(_ ++ _) 
mapList reduceLeft(_ ++ _) 

最后,你要注意,你这里做的是合并的地图。当使用++来合并地图时,您只会覆盖已存在于地图中的键 - 您将不会添加重复键的值。如果你想这样做,你可以按照提供的答案here,并将它们应用于foldLeftreduceLeft。例如:

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 { _ |+| _ } 
+0

你可以使用它的元数-1的方法或方法0(尽管后者通常是灰心的)。您不能将它用于具有多个参数或多个参数列表的方法。 –

+1

更加简洁地使用scalaz:'mapList.suml'。 – lmm

+0

@Imm非常好! –