array\ sort函数根据数组< struct>中的第一个数字元素对数据进行排序

1dkrff03  于 2021-05-27  发布在  Spark
关注(0)|答案(1)|浏览(707)

我需要整理一下 array<struct> 基于结构中的特定元素。我在试着用 array_sort 函数,可以看到默认情况下它是基于第一个数字元素对数组进行排序的。这是预期的行为吗?pfb示例代码和输出。

val jsonData = """
{
"topping":
[
{ "id": "5001", "id1": "5001", "type": "None" },
{ "id": "5002", "id1": "5008", "type": "Glazed" },
{ "id": "5005", "id1": "5007", "type": "Sugar" },
{ "id": "5007", "id1": "5002", "type": "Powdered Sugar" },
{ "id": "5006", "id1": "5005", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "id1": "5004", "type": "Chocolate" },
{ "id": "5004", "id1": "5003", "type": "Maple" }
]
}
"""
val json_df = spark.read.json(Seq(jsonData).toDS)
val sort_df = json_df.select(array_sort($"topping").as("sort_col"))
display(sort_df)

输出

如您所见,上面的输出是基于 id 元素,它是结构中的第一个数值元素。
有没有办法指定可以进行排序的元素?

tzdcorbm

tzdcorbm1#

这是预期的行为吗?
简而言之,是的!
对于具有struct类型元素的数组,它比较第一个字段以确定顺序,如果它们相等,则比较第二个字段,依此类推。通过修改输入数据示例使其在中具有相同的值,您可以很容易地看到这一点 id 对于2行,您将注意到顺序是由第二个字段决定的。
这个 array_sort 函数使用集合操作arraysort。如果您仔细查看代码,就会发现它是如何处理structtype之类的复杂数据类型的。
有没有办法指定可以进行排序的元素?
一种方法是使用 tranform 函数更改结构字段的位置,以便第一个字段包含希望排序基于的值。示例:如果要按字段排序 type :

val transform_expr = "TRANSFORM(topping, x -> struct(x.type as type, x.id as id, x.id1 as id1))"

val transform_df = json_df.select(expr(transform_expr).alias("topping_transform"))

transfrom_df.show(fasle)

//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|topping_transform                                                                                                                                                                  |
//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|[[None, 5001, 5001], [Glazed, 5002, 5008], [Sugar, 5005, 5007], [Powdered Sugar, 5007, 5002], [Chocolate with Sprinkles, 5006, 5005], [Chocolate, 5003, 5004], [Maple, 5004, 5003]]|
//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

val sort_df = transform_df.select(array_sort($"topping_transform").as("sort_col"))

sort_df.show(false)

//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|sort_col                                                                                                                                                                           |
//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//|[[Chocolate, 5003, 5004], [Chocolate with Sprinkles, 5006, 5005], [Glazed, 5002, 5008], [Maple, 5004, 5003], [None, 5001, 5001], [Powdered Sugar, 5007, 5002], [Sugar, 5005, 5007]]|
//+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

相关问题