[英]Scala How to Intersect Maps of types Map[String, Double] inside a List of: List[Map[String, Double]]
So I have a list of maps: List[Map[String, Double]].所以我有一个地图列表:List[Map[String, Double]]。 An example of it would be:
一个例子是:
List(Map("A" -> 1.1, "B" -> 2.5, "E" -> 3.5, "C" -> 1.6, "D" -> 0.9),
Map("A" -> 0.8, "C" -> 2.1, "D" -> 2.8),
Map("C" -> 2.2, "D" -> 2.9, "A" -> 3.4),
Map("B" -> 0.4, "D" -> 1.8, "E" -> 0.234, "A" -> 3.7))
What I want to do is to get the intersect of all of the maps together so then it looks like:我想要做的是将所有地图的交集放在一起,然后看起来像:
For example, for A: (1.1 + 0.8 + 3.4 + 3.7)/4 = 2.25
for D: (0.9 + 2.8 + 2.9 + 1.8)/4 = 2.1
List(Map("A" -> 2.25,"D" -> 2.1))
Is there a way to get the intersected list of map above using built in functions only?有没有办法只使用内置函数来获取上面地图的交叉列表? The values are the average of all of the keys in the four maps combined.
这些值是四个映射中所有键的平均值。
Try first using reduce
to keep only duplicate keys and add up all the values, and then use mapValues
to get the mean:首先尝试使用
reduce
只保留重复的键并将所有值相加,然后使用mapValues
来获取平均值:
val maps = List(...)
val intersected = maps
.reduce { (m1, m2) =>
m1.keySet.intersect(m2.keySet).map(key => (key, m1(key) + m2(key))).toMap
}
.view
.mapValues(_ / maps.size)
.toMap
This question is similar. 这个问题类似。
Have to be careful that the input isn't empty.必须小心输入不为空。
val lm : List[Map[String,Double]] =
List(Map("A" -> 1.1, "B" -> 2.5, "E" -> 3.5, "C" -> 1.6, "D" -> 0.9)
,Map("A" -> 0.8, "C" -> 2.1, "D" -> 2.8)
,Map("C" -> 2.2, "D" -> 2.9, "A" -> 3.4)
,Map("B" -> 0.4, "D" -> 1.8, "E" -> 0.234, "A" -> 3.7))
val len = lm.length
val res = if (len > 0)
lm.map(_.keySet)
.reduce(_ intersect _)
.map(k => (k, lm.map(_(k)).sum/len))
.toMap
else Map.empty[String,Double]
//res: Map[String,Double] = Map(A -> 2.25, D -> 2.1)
Assuming we have:假设我们有:
val list = List(Map("A" -> 1.1, "B" -> 2.5, "E" -> 3.5, "C" -> 1.6, "D" -> 0.9),
Map("A" -> 0.8, "C" -> 2.1, "D" -> 2.8),
Map("C" -> 2.2, "D" -> 2.9, "A" -> 3.4),
Map("B" -> 0.4, "D" -> 1.8, "E" -> 0.234, "A" -> 3.7))
Another option you have is (only Scala 2.13):您拥有的另一个选择是(仅限 Scala 2.13):
val stringToDoubles =
list.flatten
.groupMap(_._1)(_._2)
.filter(_._2.size == list.size)
.map(keyAndValues => (keyAndValues._1, keyAndValues._2.sum / list.size))
Code run can be found at scastie .代码运行可以在scastie找到。
In Scala 2.12 and below it will be:在 Scala 2.12 及以下版本中,它将是:
val stringToDoubles =
list.flatten
.groupBy(_._1)
.filter(_._2.size == list.size)
.map(keyAndValues => (keyAndValues._1, keyAndValues._2.map(_._2).sum / list.size))
If you are open to using external libraries, this becomes very simple with cats :如果您愿意使用外部库,这对于cat 来说变得非常简单:
import cats.data.NonEmptyList
import cats.syntax.all._
val data = NonEmptyList.of(
Map("A" -> 1.1, "B" -> 2.5, "E" -> 3.5, "C" -> 1.6, "D" -> 0.9),
Map("A" -> 0.8, "C" -> 2.1, "D" -> 2.8),
Map("C" -> 2.2, "D" -> 2.9, "A" -> 3.4),
Map("B" -> 0.4, "D" -> 1.8, "E" -> 0.234, "A" -> 3.7)
)
val result =
data
.nonEmptySequence
.fmap { group =>
val (sum, count) = group.foldMap(_ -> 1)
sum / count
}
// result: Map[String, Double] = HashMap(A -> 2.25, D -> 2.1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.