我正在试图找出如何在给定两个数据集的情况下消除交叉连接中的重复。
例如客户端(clientDs)
clientDs = sc.parallelize(List('c1', 'c2', 'c3'))
clientMatrixDs = clientDs.join(clientDs)
clientProduct.show()
-- output
c1, c1
c1, c2
c1, c3
c2, c1
c2, c2
c2, c3
c3, c1
c3, c2
c3, c3
在这种情况下, (c1,c2)和(c2,c1)都是重复的,我需要重复它
我不知道该怎么做
在这里寻找一些想法。
答案 0 :(得分:2)
在您的示例中,您有一堆Tuple2[String, String]
个问题,问题是您希望Tuple2
只有(a, b) == (b, a)
所在的平等。这就是distinct
不适合你的原因。因此,您必须提供自己的自定义相等。
问题是你不想覆盖Tuple2
的{{1}}版本,因为这可能很危险,所以你可以在某个地方提供自定义等于:
equals
然后您可以在def customEquals(tuple1: (String, String), tuple2: (String, String)) = {
tuple1 == tuple2 || (tuple1._1 == tuple2._2 && tuple1._2 == tuple2._1)
}
中使用此功能来摆脱重复项的自定义定义:
filter
答案 1 :(得分:0)
RDD
有一个方法distinct()
,该方法可以作为等效文件使用,例如List
。但是,我不知道它的表现。
修改强>
然而,自从(a, b) != (b, a)
以来,这在scala中不起作用。所以你必须交换一些元素,以确保你没有得到任何双打。
如果您的类型有一些订购,您可以将所有配对映射到订购的等价物。例如,将(2, 1)
映射到(1, 2)
,将(3, 4)
映射到(3, 4)
。然后,您可以使用distinct
,这将删除所有重复项。
val distinctPairsRDD: RDD[(T, T)] = rdd.map{
case (a, b) if a <= b => (a, b)
case (a, b) => (b, a)
}.distinct()
如果您没有这样的排序,您可以用一些Set
替换您的配对,这些配对是无序的。因此,您可以按照以下方式映射RDD
:
val distinctRDD: RDD[Set[T]] = rdd.map {
case (a, b) => Set(a, b)
}.distinct()
然而,这将失去您的类型,因此您可能需要在此之后返回配对。要做到这一点,请记住Set
本身没有重复项,因此如果您有一对具有相同元素的对,则它将被映射到只有一个元素的集合。
所以你必须做到以下几点:
val distinctPairs: RDD[(T, T)] = distinctRdd.collect {
case Set(a) => (a, a)
case Set(a, b) => (a, b)
}
collect
可以替换为map
,但如果稍后更改代码,可能会导致一些MatchError。这使得所有其他情况(如果碰巧有空集或具有多于两个元素的集合)被丢弃,因此请确保您在将来的更改(而不是RuntimeError或丢弃的元素)上更喜欢什么。
<强> TL; DR 强>
尝试在你的对中订购元素,以获得单一性。如果这不起作用,请使用Set
,但它会更复杂。