创建Spark存在用户定义的函数,其功能类似于Scala Array#exists函数

时间:2017-08-25 08:31:07

标签: scala apache-spark apache-spark-sql user-defined-functions

Scala有一个Array#exists函数,其工作方式如下:

Array(1, 2, 5).exists(_ % 2 == 0) // true

我想创建一个类似的Spark存在函数。假设我们有以下sourceDF

+---------+
|     nums|
+---------+
|[1, 4, 9]|
|[1, 3, 5]|
+---------+

我希望能够写出这样的东西:

val actualDF = sourceDF.withColumn(
  "nums_has_even",
  exists(col("nums"), (x: Int) => x % 2 == 0)
)

这是我写的代码:

def existsInt(arr: Array[Int], f: (Int => Boolean)): Boolean = {
  arr.exists(f(_))
}

val exists = udf[Boolean, Array[Int], (Int => Boolean)](existsInt)

我明白为什么我的代码无效。 UDF需要列参数,而匿名函数不是Column对象。在lit中包装匿名函数不起作用:

exists(col("nums"), lit((x: Int) => x % 2 == 0)) // doesn't work

如何让此代码正常工作?

1 个答案:

答案 0 :(得分:2)

你非常接近:

def existsInt(f: (Int => Boolean)) = udf {
  (arr: Seq[Int]) => arr.exists(f(_))  // Not Array!
}

用法:

existsInt((x: Int) => x % 2 == 0)(col("nums"))

你甚至可以:

scala.reflect.runtime.universe._

def exists[T : TypeTag](f: (T => Boolean)) = udf[Boolean, Seq[T]]{
  (arr: Seq[T]) => arr.exists(f(_))  // Not Array!
}

exists[Int]((x: Int) => x % 2 == 0).apply(col("nums"))