删除Spark数组列中的重复项

zby*_*ekt 5 java scala apache-spark apache-spark-sql apache-spark-dataset

我有一个给定的DataSet:

+-------------------+--------------------+
|               date|            products|
+-------------------+--------------------+
|2017-08-31 22:00:00|[361, 361, 361, 3...|
|2017-09-22 22:00:00|[361, 362, 362, 3...|
|2017-09-21 22:00:00|[361, 361, 361, 3...|
|2017-09-28 22:00:00|[360, 361, 361, 3...|
Run Code Online (Sandbox Code Playgroud)

产品列是包含可能重复项的字符串数组。

我想删除此重复项(在一排之内)

我所做的基本上是编写像这样的UDF函数

 val removeDuplicates: WrappedArray[String] => WrappedArray[String] = _.distinct
 val udfremoveDuplicates = udf(removeDuplicates)
Run Code Online (Sandbox Code Playgroud)

这个解决方案给了我适当的结果:

+-------------------+--------------------+--------------------+
|               date|            products|       rm_duplicates|
+-------------------+--------------------+--------------------+
|2017-08-31 22:00:00|[361, 361, 361, 3...|[361, 362, 363, 3...|
|2017-09-22 22:00:00|[361, 362, 362, 3...|[361, 362, 363, 3...|
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. Spark是否提供更好/更有效的方式来获得此结果?

  2. 我当时正在考虑使用地图-但是如何获取所需的列作为列表,以便能够像在removeDuplicates lambda中那样使用'distinct'方法?

编辑:我用java标记标记了此主题,因为与我所用的语言(scala或java)无关,我都会收到answear :) Edit2:typos

Sim*_*Sim 3

问题中提出的方法(使用 UDF)是最好的方法,因为spark-sql没有内置的原语来唯一化数组。

如果您正在处理大量数据和/或数组值具有独特的属性,那么值得考虑 UDF 的实现

WrappedArray.distinctmutable.HashSet在幕后构建一个,然后遍历它以构建不同元素的数组。从性能角度来看,这可能存在两个问题:

  1. Scala 的可变集合效率并不高,这就是为什么在 Spark 内部您会发现大量 Java 集合和while循环。如果您需要极限性能,您可以使用更快的数据结构来实现您自己的通用不同。

  2. 的通用实现distinct不会利用数据的任何属性。例如,如果数组平均很小,那么直接构建到数组中并对重复项进行线性搜索的简单实现可能比构建复杂数据结构的代码执行得更好,尽管理论上很O(n^2)复杂。再比如,如果值只能是小范围内的数字,或者是小集合中的字符串,则可以通过位集实现唯一性。

同样,只有当您拥有大量数据时才应考虑这些策略。您的简单实现非常适合几乎所有情况。