当前
+-------+---------------------------------------------------------------------------+
|ID |map |
+-------+---------------------------------------------------------------------------+
|105 |[{bia, {4 -> 1}}, {compton, {5 -> 1}}, {alcatraz, {3 -> 6}}] |
|106 |[{compton, {4 -> 5}}] |
|107 |[{compton, {5 -> 99}}] |
|108 |[{bia, {1 -> 5}}, {compton, {1 -> 1}}] |
|101 |[{alcatraz, {1 -> 2}}] |
|102 |[{alcatraz, {1 -> 2}}] |
|103 |[{alcatraz, {1 -> 2}}, {alcatraz, {2 -> 2}}, {alcatraz, {3 -> 2}}] |
|104 |[{alcatraz, {1 -> 4}}, {alcatraz, {2 -> 2}}, {alcatraz, {3 -> 2}}] |
+-------+---------------------------------------------------------------------------+所需
+-------+---------------------------------------------------------------------------+
|ID |map |
+-------+---------------------------------------------------------------------------+
|105 |{bia, {4 -> 1}}, {compton, {5 -> 1}}, {alcatraz, {3 -> 6}} |
|106 |{compton, {4 -> 5}} |
|107 |{compton, {5 -> 99}} |
|108 |{bia, {1 -> 5}}, {compton, {1 -> 1}} |
|101 |{alcatraz, {1 -> 2}} |
|102 |{alcatraz, {1 -> 2}} |
|103 |{alcatraz, {1 -> 2, 2 -> 2, 3 -> 2} |
|104 |{alcatraz, {1 -> 4, 2 -> 2, 3 -> 2} |
+-------+---------------------------------------------------------------------------+我希望最终的映射是,第一个映射级别是位置的关键(例如,alcatraz、bia、compton),第二级是代表组的数字,最终值是计数。
我通过做这样的事情得到了当前的桌子:
.groupBy(col("ID")).agg(collect_list(map($"LOCATION", map($"GROUP", $"COUNT"))) as "map")为了更清晰起见,JSON表示所需的格式
{
"alcatraz": {
"1": 100,
"2": 300
},
"bia": {
"2": 767
},
"compton": {
"1": 888,
"2": 999,
"3": 1000
},
}我看到了其他一些用于合并简单映射的堆栈溢出帖子,但是因为它是地图的映射,所以这些解决方案都不起作用。
我一直在和udf一起玩,但运气不好。在scala中有一个简单的方法来实现我的目标吗?
发布于 2022-11-03 01:38:12
我最后所做的是使用这个定义的udf:
val joinMap = udf { values: Seq[Map[String, Map[String, Int]]] => {
var newMap: scala.collection.mutable.Map[String, Map[String, Int]] = scala.collection.mutable.Map[String, Map[String, Int]]()
for (value <- values) {
for ((k, v) <- value) {
for ((sub_k, sub_v) <- v) {
if (newMap.contains(k)) {
newMap(k) += (sub_k -> sub_v)
} else {
newMap(k) = v
}
}
}
}
newMap
} }你可以通过做
.withColumn("map", joinMap(col("map")))发布于 2022-11-03 17:57:25
如果您的作用域中有猫,您可以这样做:
def mergeMaps(values: Seq[Map[String, Map[String, Int]]]): Map[String, Map[String, Int]] = {
import cats.implicits._
values.foldLeft(Map.empty)(_ |+| _)
}(注意:猫提供了更紧凑的语法,但这将使其更不明显。)
但是要小心:如果两个“内部映射”有相同的键,上面会添加整数值,因此Seq(Map("1" -> Map("1" -> 1)), Map("1" -> Map("1" -> 1)))将合并到Map("1" -> Map("1" -> 2))中。如果这是一个问题,并且需要与解决方案中的行为完全相同的行为,您可以这样修改解决方案:
def mergeMaps(values: Seq[Map[String, Map[String, Int]]]): Map[String, Map[String, Int]] = {
import cats.implicits._
implicit val takeRightIntSemiGroup = new cats.Semigroup[Int] {
def combine(x: Int, y: Int): Int = y
}
values.foldLeft(Map.empty)(_ |+| _)
}https://stackoverflow.com/questions/74297149
复制相似问题