写在前面
在实际开发中,我遇到一个场景:将源数据读取进来,加载为DataFrame之后,其中一个处理步骤是,需要将某一列的数据单独提取出来作为一个数组,然后传递给后面的udf()函数。
需求:读取的是日期字段列,因为在数据仓库中,各个数据表的数据形态是不一致的,每种数据形态都有自己的日期字段,一般来说:比如,快照表我们的日期字段可能是DW_XX_DT。这个就看自己公司如何定义了。
我这里遇到的情况是:日期字段列中有空字符串""(读出来是null),还有中文字符"为空",然后还有DW_XX_DT 或 Dw_xx_Dt 这种大小写。
类似这种:把上面这个转成下面这个
最后得到的是:转大写 、 去重 、去空字符串 、 去"为空"字符 的一个数组。
我这里封装成了一个方法:
def getTableFiledArray(t :DataFrame): mutable.Buffer[String] = {
var returnTableFiledArray:mutable.Buffer[String] = t.select("日期字段")
.filter(!_.isNullAt(0)) // 去掉null
.distinct() // 去掉本身重复的
.as(Encoders.STRING).collect().toBuffer // Dataset[Row] ==> mutable.Buffer[String]
// ================接下来就是一些Scala数组的操作================
// delete elements from an Array or ArrayBuffer
returnTableFiledArray -= ("为空")
for ( i <- 0 until returnTableFiledArray.length){
// 转大写
returnTableFiledArray(i) = returnTableFiledArray(i).toUpperCase()
}
returnTableFiledArray.distinct
}
直接调用:
inputDF.show()
val tableFiledArray = getTableFiledArray(inputDF.select("日期字段"))
for (tableFiled <- tableFiledArray){
println(tableFiled)
}
得到如下结果:
后面我就可以把 tableFiledArray 传递给udf()函数了。
参考:
https://hello-scala.com/201-scala-arraybuffer-examples.html
https://alvinalexander.com/scala/how-to-delete-array-arraybuffer-elements-scala-cookbook/
-------------扩展-------------
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) {
array(i) = x; i += 1 }
array
}