如何在Spark DataFrame中按指定字段排序结构体类型数组?
在Spark DataFrame中对结构体数组按指定字段排序的解决方案
嘿,这问题我熟!要在Spark DataFrame里给结构体类型的数组按指定字段排序,Spark 3.0+提供了非常方便的内置函数,不用写复杂的UDF就能搞定。我结合你的代码示例来一步步说明:
首先补全你的示例场景
看起来你定义了ABC结构体,接下来我们创建一个包含结构体数组的DataFrame(补全你没写完的second部分):
import java.sql.Date import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions._ object SortQuestion extends App{ val spark = SparkSession.builder().appName("local").master("local[*]").getOrCreate() import spark.implicits._ case class ABC(a: Int, b: Int, c: Int) // 先创建单个结构体数据(你的first部分) val first = Seq( ABC(1, 2, 3), ABC(1, 3, 4), ABC(2, 4, 5), ABC(2, 5, 6) ).toDF("a", "b", "c") // 创建包含结构体数组的DataFrame(补全你的second部分) val df = Seq( (1, "group1", Seq(ABC(1,3,4), ABC(1,2,3))), (2, "group2", Seq(ABC(2,5,6), ABC(2,4,5))) ).toDF("id", "group_name", "abc_array") df.show(truncate = false) }
执行后原始数据会是这样:
+---+----------+------------------------+ |id |group_name|abc_array | +---+----------+------------------------+ |1 |group1 |[{1,3,4}, {1,2,3}] | |2 |group2 |[{2,5,6}, {2,4,5}] | +---+----------+------------------------+
方法1:使用Spark内置函数(推荐,Spark 3.0+)
用transform遍历数组,配合sort_by指定排序字段,这是最优雅且性能最好的方式:
按结构体字段b升序排序
// 对abc_array数组按b字段升序排序,生成新列sorted_abc_array val sortedDF = df.withColumn( "sorted_abc_array", transform($"abc_array", arr => sort_by(arr, x => x.b)) ) sortedDF.select("id", "group_name", "sorted_abc_array").show(truncate = false)
结果会变成:
+---+----------+------------------------+ |id |group_name|sorted_abc_array | +---+----------+------------------------+ |1 |group1 |[{1,2,3}, {1,3,4}] | |2 |group2 |[{2,4,5}, {2,5,6}] | +---+----------+------------------------+
按结构体字段b降序排序
只需要在排序字段后面加上.desc()即可:
val sortedDFDesc = df.withColumn( "sorted_abc_array_desc", transform($"abc_array", arr => sort_by(arr, x => x.b.desc)) )
方法2:使用UDF(兼容Spark低版本)
如果你的Spark版本低于3.0,没法用transform和sort_by,可以自定义UDF来实现:
// 定义UDF:接收ABC类型的数组,按b字段排序后返回 val sortAbcArrayUdf = udf((arr: Seq[ABC]) => arr.sortBy(_.b)) val sortedDFByUdf = df.withColumn( "sorted_abc_array", sortAbcArrayUdf($"abc_array") )
注意:UDF的性能比内置函数差,能不用尽量不用。
关键知识点强调
transform函数:用来对数组中的每个元素应用转换逻辑,这里我们用它来处理整个数组的排序。sort_by函数:专门用来对数组按指定字段排序,支持升序/降序配置。- 如果你要按多个字段排序,只需要把排序条件写成数组即可,比如
sort_by(arr, x => array(x.a, x.b.desc))。
内容的提问来源于stack exchange,提问作者addmeaning
相关产品推荐
相关产品推荐

