Scala Regex UDF 获取查询参数值并将它们转换为逗号分隔列表
Scala Regex UDF to grab query parameter values and transform them into comma delimited list
我有类似于以下内容的数据:
one=1&two=22222&three=&four=4f4
如您所见,缺少变量 3 的值。我想使用 Scala Regex 获取所有值并 return 它们以逗号分隔。
期望的输出:
1,22222,,4f4
另一个更需要的可能输出:
1,22222,undefined,4f4
这是我当前的代码(我将 scala 与 Spark 2.0 一起用于数据框):
def main(args: Array[String]) {
...
val pattern : scala.util.matching.Regex = """[^&?]*?=([^&?]*)""".r
df.select(transform(pattern)($"data").alias("csvData")).take(100).foreach(println)
}
def transform(pattern: scala.util.matching.Regex) = udf(
(dataMapping: String) => pattern.findAllIn(dataMapping).toList
)
哪个 returns:
[WrappedArray(one=1, two=22222, three=, four=4f4)]
[WrappedArray(...)]
我认为我可以在我的 "transform" udf 函数上做得更好,但我对 Scala 很陌生,不确定如何只匹配第一组和 return 它们以逗号分隔。我想我会在我的解决方案中使用类似 m => m.group(1) 的东西,但我不确定。谢谢你的建议。
如果您有多个列,您最好使用 UDF
:
scala> val df = Seq(("one=1&two=22222&three=&four=4f4", 1)).toDF("a", "b")
df: org.apache.spark.sql.DataFrame = [a: string, b: int]
scala> df.show
+--------------------+---+
| a| b|
+--------------------+---+
|one=1&two=22222&t...| 1|
+--------------------+---+
scala> val p = """[one|two|three|four]\=([\d|\W|\w]+)""".r
p: scala.util.matching.Regex = [one|two|three|four]\=([\d|\W|\w]+)
scala> :pa
// Entering paste mode (ctrl-D to finish)
val regexUDF = udf( (x: String) =>
x.split("&").map(p.findFirstMatchIn(_).map(_.group(1)).getOrElse(null)))
)
// Exiting paste mode, now interpreting.
regexUDF: org.apache.spark.sql.expressions.UserDefinedFunction = UserDefinedFunction(<function1>,ArrayType(StringType,true),Some(List(StringType)))
scala> val df2 = df.withColumn("a", regexUDF($"a"))
df2: org.apache.spark.sql.DataFrame = [a: array<string>, b: int]
scala> df2.show
+--------------------+---+
| a| b|
+--------------------+---+
|[1, 22222, null, ...| 1|
+--------------------+---+
scala> df2.collect.foreach{println}
[WrappedArray(1, 22222, null, 4f4),1]
我有类似于以下内容的数据:
one=1&two=22222&three=&four=4f4
如您所见,缺少变量 3 的值。我想使用 Scala Regex 获取所有值并 return 它们以逗号分隔。
期望的输出:
1,22222,,4f4
另一个更需要的可能输出:
1,22222,undefined,4f4
这是我当前的代码(我将 scala 与 Spark 2.0 一起用于数据框):
def main(args: Array[String]) {
...
val pattern : scala.util.matching.Regex = """[^&?]*?=([^&?]*)""".r
df.select(transform(pattern)($"data").alias("csvData")).take(100).foreach(println)
}
def transform(pattern: scala.util.matching.Regex) = udf(
(dataMapping: String) => pattern.findAllIn(dataMapping).toList
)
哪个 returns:
[WrappedArray(one=1, two=22222, three=, four=4f4)]
[WrappedArray(...)]
我认为我可以在我的 "transform" udf 函数上做得更好,但我对 Scala 很陌生,不确定如何只匹配第一组和 return 它们以逗号分隔。我想我会在我的解决方案中使用类似 m => m.group(1) 的东西,但我不确定。谢谢你的建议。
如果您有多个列,您最好使用 UDF
:
scala> val df = Seq(("one=1&two=22222&three=&four=4f4", 1)).toDF("a", "b")
df: org.apache.spark.sql.DataFrame = [a: string, b: int]
scala> df.show
+--------------------+---+
| a| b|
+--------------------+---+
|one=1&two=22222&t...| 1|
+--------------------+---+
scala> val p = """[one|two|three|four]\=([\d|\W|\w]+)""".r
p: scala.util.matching.Regex = [one|two|three|four]\=([\d|\W|\w]+)
scala> :pa
// Entering paste mode (ctrl-D to finish)
val regexUDF = udf( (x: String) =>
x.split("&").map(p.findFirstMatchIn(_).map(_.group(1)).getOrElse(null)))
)
// Exiting paste mode, now interpreting.
regexUDF: org.apache.spark.sql.expressions.UserDefinedFunction = UserDefinedFunction(<function1>,ArrayType(StringType,true),Some(List(StringType)))
scala> val df2 = df.withColumn("a", regexUDF($"a"))
df2: org.apache.spark.sql.DataFrame = [a: array<string>, b: int]
scala> df2.show
+--------------------+---+
| a| b|
+--------------------+---+
|[1, 22222, null, ...| 1|
+--------------------+---+
scala> df2.collect.foreach{println}
[WrappedArray(1, 22222, null, 4f4),1]