想象一下以下地圖串列(可能更長):
List(
Map[String,String]("wind"->"high", "rain"->"heavy", "class"->"very late"),
Map[String,String]("wind"->"none", "rain"->"slight", "class"->"on time"),
Map[String,String]("wind"->"high", "rain"->"none", "class"->"very late"),
...
)
我怎樣才能得到以下表格:
Map("very late" -> Set(("wind",Map("high" -> 2)), ("rain",Map("heavy" -> 1, "none" -> 1))),
"on time" -> Set(("wind",Map("none" -> 1)), ("rain",Map("slight" -> 1))))
uj5u.com熱心網友回復:
這會讓你得到你想要的。
val maps = List(...)
maps.groupBy(_.getOrElse("class","no-class"))
.mapValues(_.flatMap(_ - "class").groupBy(_._1)
.mapValues(_.map(_._2).groupBy(identity)
.mapValues(_.length)
).toSet
)
問題是,你想要的不是一個好地方。
結果型別是Map[String,Set[(String,Map[String,Int])]]集合型別的大雜燴。為什么Set?這樣做的目的是什么?這有什么用?您如何從中檢索有意義的資料?
這看起來像是一個XY 問題。
uj5u.com熱心網友回復:
這里有兩個版本。
首先使用Set,它看起來像你想要的,
val grouped2 = maps.foldLeft(Map.empty[String, Set[(String, Map[String, Int])]]) {
case (acc, map) =>
map.get("class").fold(acc) { key =>
val keyOpt = acc.get(key)
if (keyOpt.isDefined) {
val updatedSet = (map - "class").foldLeft(Set.empty[(String, Map[String, Int])]) {
case (setAcc, (k1, v1)) =>
keyOpt.flatMap(_.find(_._1 == k1)).map { tup =>
setAcc ((k1, tup._2.get(v1).fold(tup._2 Map(v1 -> 1))(v => tup._2 ((v1, v 1)))))
}.getOrElse(setAcc (k1 -> Map(v1 -> 1)))
}
acc.updated(key, updatedSet)
} else {
acc (key -> (map - "class").map(tup => (tup._1, Map(tup._2 -> 1))).toSet)
}
}
}
然后使用一個Map,
val grouped1 = maps.foldLeft(Map.empty[String, Map[String, Map[String, Int]]]) {
case (acc, map) =>
map.get("class").fold(acc) { key =>
val keyOpt = acc.get(key)
if (keyOpt.isDefined) {
val updatedMap = (map - "class").foldLeft(Map.empty[String, Map[String, Int]]) {
case (mapAcc, (k1, v1)) =>
keyOpt.flatMap(_.get(k1)).map{ statMap =>
mapAcc ((k1, statMap.get(v1).fold(statMap Map(v1 -> 1))(v => statMap ((v1, v 1)))))
}.getOrElse(mapAcc (k1 -> Map(v1 -> 1)))
}
acc.updated(key, updatedMap)
} else {
acc (key -> (map - "class").map(tup => (tup._1, Map(tup._2 -> 1))))
}
}
}
我正在玩 Map版本并將其更改為Set. 過幾天,我想我不會光看上面的一切就明白了。所以,我試圖讓我盡可能理解它。將此調整為您自己的解決方案或等待其他解決方案。
uj5u.com熱心網友回復:
這是另一個實作,它使用 的keySet方法Map將兩個地圖連接在一起。
另請注意,我將輸出型別從 a 更改Map為 a Setof 元組,其第二個值是 another Map。三個嵌套Maps其中,恕我直言,更有意義。
def groupMaps[K, V](groupingKey: K, data: List[Map[K, V]]): Map[V, Map[K, Map[V, Int]]] =
data.foldLeft(Map.empty[V, Map[K, Map[V, Int]]]) {
case (acc, map) =>
map.get(key = groupingKey).fold(ifEmpty = acc) { groupingValue =>
val newValues = (map - groupingKey).map {
case (key, value) =>
key -> Map(value -> 1)
}
val finalValues = acc.get(key = groupingValue).fold(ifEmpty = newValues) { oldValues =>
(oldValues.keySet | newValues.keySet).iterator.map { key =>
val oldMap = oldValues.getOrElse(key = key, default = Map.empty[V, Int])
val newMap = newValues.getOrElse(key = key, default = Map.empty[V, Int])
val finalMap = (oldMap.keySet | newMap.keySet).iterator.map { value =>
val oldCount = oldMap.getOrElse(key = value, default = 0)
val newCount = newMap.getOrElse(key = value, default = 0)
value -> (oldCount newCount)
}.toMap
key -> finalMap
}.toMap
}
acc.updated(key = groupingValue, finalValues)
}
}
可以這樣使用:
val maps =
List(
Map("wind" -> "none", "rain" -> "none", "class" -> "on time"),
Map("wind" -> "none", "rain" -> "slight", "class" -> "on time"),
Map("wind" -> "none", "rain" -> "slight", "class" -> "late"),
Map("wind" -> "none", "rain" -> "slight")
)
val result = groupMaps(groupingKey = "class", maps)
// val result: Map[Strig, Map[String, Map[String, Int]]] =
// Map(
// on time -> Map(wind -> Map(none -> 2), rain -> Map(none -> 1, slight -> 1)),
// late -> Map(wind -> Map(none -> 1), rain -> Map(slight -> 1))
// )
如果你需要保持你要求的輸出型別,那么你可以.mapValue(_.toSet)在最后做一個foldLeft
你可以在這里看到運行的代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/387347.html
上一篇:如何從Prometheus服務器獲取按特定標簽過濾的所有指標名稱
下一篇:如何用貓效應取消可完成的未來3
