我有N个地图(Map [String,Double]),每个地图都有相同的密钥集。让我们说出如下内容:
resultMap = ("elem1": 3.0, "elem2": 5.0, "elem3": 2.0)
我需要返回一个新的地图,其中包含那些输入地图的元素平均值:
[
{
key: some_key,
payload: { ... }
},
{
key: some_key,
payload: { ... }
},
{
key: some_key,
payload: { ... }
},
...
]
scala中最干净的方法是什么?最好不要使用额外的外部库。
这一切都发生在Spark *中。因此,任何暗示特定于火花的使用的答案都可能有所帮助。
答案 0 :(得分:2)
一种选择是将所有地图转换为Seqs,将它们合并为单个Seq,按键分组并取平均值:
val maps = Seq(map1, map2, map3)
maps.map(_.toSeq).reduce(_++_).groupBy(_._1).mapValues(x => x.map(_._2).sum/x.length)
// res6: scala.collection.immutable.Map[String,Double] = Map(elem1 -> 3.0, elem3 -> 2.0, elem2 -> 5.0)
答案 1 :(得分:1)
由于您的问题已使用 apache-spark 标记,因此您可以将地图合并到RDD[Map[String, Double]]
作为
scala> val rdd = sc.parallelize(Seq(Map("elem1"-> 2.0, "elem2"-> 4.0, "elem3"-> 3.0),Map("elem1"-> 4.0, "elem2"-> 1.0, "elem3"-> 1.0),Map("elem1"-> 3.0, "elem2"-> 10.0, "elem3"-> 2.0)))
rdd: org.apache.spark.rdd.RDD[scala.collection.immutable.Map[String,Double]] = ParallelCollectionRDD[1] at parallelize at <console>:24
然后,您可以使用flatMap
将地图的条目展平到各行并使用groupBy
功能密钥和sum
分组值和devide
分组映射的大小。你应该得到你想要的输出
scala> rdd.flatMap(row => row).groupBy(kv => kv._1).mapValues(values => values.map(value => value._2).sum/values.size)
res0: org.apache.spark.rdd.RDD[(String, Double)] = MapPartitionsRDD[5] at mapValues at <console>:27
scala> res0.foreach(println)
[Stage 0:> (0 + 0) / 4](elem2,5.0)
(elem3,2.0)
(elem1,3.0)
希望答案有用