scala—将键与maptype列中values数组中的第一个元素连接起来

umuewwlo  于 2021-07-14  发布在  Spark
关注(0)|答案(1)|浏览(249)

下面给出了Dataframe的模式。

|-- idMap: map (nullable = true)
|    |-- key: string
|    |-- value: array (valueContainsNull = true)
|    |    |-- element: struct (containsNull = true)
|    |    |    |-- id: string (nullable = true)
|    |    |    |-- linked: boolean (nullable = true)

例如,如果一行中有3个键,我将尝试将其转换为该格式的新字符串列 key1:id;key2:id;key3:id 其中id是索引0处元素的一部分。
我试过的是
收集列表的键
从键列表创建列列表

val expr = new scala.collection.mutable.ListBuffer[org.apache.spark.sql.Column]
keyList.foldLeft(expr)((expr, key) => expr += (lit(key), lit(":"), col("idMap")(key)(0)("id"), lit(";")))

使用传递给concat的列列表添加一个新列

val finalDf = df.withColumn("concatColumn", concat(expr.toList:_*))

它给了我一个空列,所以我假设这个方法是有缺陷的。如有任何意见,我们将不胜感激。
编辑:@mck的答案有效。在第3步中使用concat\u ws也可以。

val finalDf = df.withColumn("concatColumn", concat_ws(expr.toList:_*))
2mbi3lxu

2mbi3lxu1#

如果你有spark 3,你可以用 transform_values 转换Map列以获得所需的输出。

// sample dataframe
val df = spark.sql("select map('key1', array(struct('id1' id, true linked)), 'key2', array(struct('id2' id, false linked))) idMap")

val df2 = df.withColumn(
    "concatColumn", 
    expr("""
        concat_ws(';', 
            map_values(
                transform_values(
                    idMap, 
                    (k, v) -> concat(k, ':', transform(v, y -> y.id)[0])
                )
            )
        ) 
    """)
)

df2.show(false)
+-----------------------------------------------+-----------------+
|idMap                                          |concatColumn     |
+-----------------------------------------------+-----------------+
|[key1 -> [[id1, true]], key2 -> [[id2, false]]]|key1:id1;key2:id2|
+-----------------------------------------------+-----------------+

相关问题