Scala 连接列表中的地图
Scala concatenate maps from a list
有了 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 )
两个选项都未编译(第一个说 "missing parameter type for expanded function (x, y) => x ++ y
",第二个说 "type mismatch; found (Map[String, Int], Map[String, Int]) => Map[String, Int];
required: String
")。
我想实现一个经典的解决方案,用于连接不可变映射列表,例如 List( Map("apple" -> 5, "pear" -> 7), Map("pear" -> 3, "apricot" -> 0) )
会产生 Map("apple" -> 5, "pear" -> 10, "apricot" -> 0)
。
使用 Scala 2.10.5
。
您需要在foldLeft
前加一个点。您只能在特殊条件下使用 spaces 而不是点,例如对于恰好具有 1 个参数的方法(arity-1 方法):
val map = mapList.foldLeft(Map[String, Int]()) ( _ ++ _ )
您可以阅读有关方法调用最佳实践的更多信息here。
您可能还对 reduce
方法感兴趣,它们是 fold
方法的特殊版本,其中 return 类型与集合。例如 reduceLeft
使用集合的第一个元素作为 foldLeft
的种子。当然,由于这依赖于第一个元素的存在,如果集合为空,它会抛出异常。由于 reduceLeft
只接受 1 个参数,您可以更轻松地使用 space 来调用方法:
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 { _ |+| _ }
有了 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 )
两个选项都未编译(第一个说 "missing parameter type for expanded function (x, y) => x ++ y
",第二个说 "type mismatch; found (Map[String, Int], Map[String, Int]) => Map[String, Int];
required: String
")。
我想实现一个经典的解决方案,用于连接不可变映射列表,例如 List( Map("apple" -> 5, "pear" -> 7), Map("pear" -> 3, "apricot" -> 0) )
会产生 Map("apple" -> 5, "pear" -> 10, "apricot" -> 0)
。
使用 Scala 2.10.5
。
您需要在foldLeft
前加一个点。您只能在特殊条件下使用 spaces 而不是点,例如对于恰好具有 1 个参数的方法(arity-1 方法):
val map = mapList.foldLeft(Map[String, Int]()) ( _ ++ _ )
您可以阅读有关方法调用最佳实践的更多信息here。
您可能还对 reduce
方法感兴趣,它们是 fold
方法的特殊版本,其中 return 类型与集合。例如 reduceLeft
使用集合的第一个元素作为 foldLeft
的种子。当然,由于这依赖于第一个元素的存在,如果集合为空,它会抛出异常。由于 reduceLeft
只接受 1 个参数,您可以更轻松地使用 space 来调用方法:
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 { _ |+| _ }