如何对scala中相同键的地图求和

How to sum a map of maps of same key in scala

我有以下地图的地图:

var map1 : mutable.Map[String, Map[String, Double]]
map1("U1" -> ("a"-> 2.1, "b"->3.21, "c"->7.1), 
     "U2" -> ("a"-> 3.1, "b"->12.1, "c"->1.4)
    )

我想遍历这张地图并以我得到以下方式合并所有值:

finalMap = ("a"->5.2, "b"->15.22, "c"->8.5)

我遇到了 this 并为解决方案导入了 scalaz,但我不太清楚如何在可迭代值上使用 |+|

我正在使用以下代码:

finalMap : Map[String, Double]()
map1.values.foreach{ (valueMap : Map[String, Double]) => 
  finalMap  |+| valueMap 
}

有关如何更正此问题的任何指示

首先,使用vals和不可变数据结构。其次,查看如何初始化集合;网络上有很多很多例子。

val map1 = Map("U1" -> Map("a"-> 2.1, "b"->3.21, "c"->7.1), 
               "U2" -> Map("a"-> 3.1, "b"->12.1, "c"->1.4))

最后,您要做的是 reducevalues 中的所有 Map 合并为一个 Map。你可以这样做:

val finalMap = map1.values.reduce(_ |+| _)
// finalMap: Map[String,Double] = Map(a -> 5.2, b -> 15.31, c -> 8.5)

如果您认为 map1 可能为空,请改用 fold,这基本上是一个 reduce,您可以在其中给出一个初始值:

map1.values.fold(Map.empty)(_ |+| _)
// res0: Map[String,Double] = Map(a -> 5.2, b -> 15.31, c -> 8.5)

val emptyMap = Map.empty[String, Map[String, Double]]
emptyMap.values.fold(Map.empty)(_ |+| _)
// res1: Map[String,Double] = Map()

补充dhg的回答:

首先,要在 Map[A, B] 上使用 |+|,我们需要一个 Semigroup[B] 实例。在这种情况下 Semigroup[Double]。但是 scalaz 本身不会给你这个实例,因为它不会遵循正确的 Semigroup 实例 (related scalaz issue) 的 rules/laws。

不用绝望,因为我们仍然可以从项目scalaz-outlaws(它似乎只支持scalaz 7。1.x)中获取一个实例。使用 Double outlaw 实例,我们现在可以组合两个 Double,同时忽略敦促我们不要使用 Monoid[Double] 因为它不遵守法律的弃用消息:

import scalaz.syntax.semigroup._
import scalaz.outlaws.std.double._

1.0 |+| 2.0
// <console>:18: warning: value doubleMonoid in trait DoubleOutlawInstances 
// is deprecated: Monoid[Double] violates the associativity law
//        1.0 |+| 2.0
//        ^
// res0: Double = 3.0

其次,我们可以通过隐式使用 Monoid[Double] 而不是直接使用 |+| 来使用 scalaz 简化 reduce / fold

import scalaz.std.map._
import scalaz.outlaws.std.double._
import scalaz.syntax.foldable._

val map = Map("U1" -> Map("a"-> 2.1, "b"->3.21, "c"->7.1), 
              "U2" -> Map("a"-> 3.1, "b"->12.1, "c"->1.4))

map.concatenate
// Map[String,Double] = Map(a -> 5.2, b -> 15.309999999999999, c -> 8.5)

map.concatenate 类似于

map.values.fold(Monoid[Map[String, Double]].zero)(_ |+| _)