You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark中如何将多行Map合并为单个Map?

问题描述

我当前有一个DataFrame,执行以下代码:

df
.groupBy($"letters")
.agg(collect_list($"numbers").as("numbers"))
.select(map($"letters",$"numbers").as("data"))
.agg(collect_list($"data").as("data"))
.select(to_json($"data").as("output"))
.show(false)

得到输出:

+------------------------------------------+
|output                                    |
+------------------------------------------+
|[{"abc":["123","456"]},{"def":["123"]}]   |
+------------------------------------------+

需要将其转换为以下单个JSON对象格式(无外层数组):

+------------------------------------------+
|output                                    |
+------------------------------------------+
|{"abc":["123","456"],"def":["123"]}       |
+------------------------------------------+

当前DataFrame的结构为:

res34: org.apache.spark.sql.DataFrame = [data: array<map<string,array<string>>>]
解决方案

核心思路是直接将所有分组的键值对合并为一个全局Map,而非收集多个Map形成数组。提供两种实现方式:

方式一:使用map_from_entries(推荐)

df
  .groupBy($"letters")
  .agg(collect_list($"numbers").as("numbers"))
  .agg(map_from_entries(collect_list(struct($"letters", $"numbers"))).as("data"))
  .select(to_json($"data").as("output"))
  .show(false)

步骤说明:

  1. 按letters分组并收集对应numbers列表的逻辑保持不变;
  2. 通过struct($"letters", $"numbers")将每组的键值对打包为结构体,再用collect_list收集所有结构体;
  3. map_from_entries直接将结构体数组转换为一个完整的Map;
  4. 最终转JSON后得到无外层数组的单个对象。

方式二:使用map_concat(Spark 3.0+支持)

df
  .groupBy($"letters")
  .agg(collect_list($"numbers").as("numbers"))
  .select(map($"letters", $"numbers").as("data"))
  .agg(map_concat(collect_list($"data")).as("data"))
  .select(to_json($"data").as("output"))
  .show(false)

步骤说明:

  1. 先为每个分组生成独立的Map;
  2. 用collect_list收集所有分组Map,再通过map_concat将多个Map合并为一个全局Map;
  3. 转JSON后得到目标格式。

内容的提问来源于stack exchange,提问作者flame1481

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:20:36