如何在scala中对相同键的映射进行求和

时间:2016-06-07 06:56:00

标签: scala merge maps scalaz

我有以下地图地图:

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 
}

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

2 个答案:

答案 0 :(得分:3)

补充 dhg 的答案:

首先,要在$('#make').change(function(){ $.post('../ajaxmodelcar', { model: this.value }, function(data) { $('#model').html(data); }); }); 上使用|+|,我们需要Map[A, B]个实例。在这种情况下Semigroup[B]。但是scalaz本身并没有给你这个实例,因为它不会遵循正确的Semigroup[Double]实例(related scalaz issue)的规则/定律。

没有绝望,因为我们仍然可以从项目scalaz-outlaws获取一个实例(它似乎只支持scalaz 7.1.x)。使用Semigroup outlaw实例,我们现在可以合并两个Double,同时忽略弃用消息,敦促我们不要使用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 而不是直接使用reduce来使用scalaz简化fold / Monoid[Double]

|+|

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

答案 1 :(得分:0)

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

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))

最后,您要做的是将reduce Map values中的所有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() ,这基本上是@most_recent_workout,您可以在其中提供初始值:

nil