如何在Spark中使用MapReduce查找集合中的所有两对集合和元素?

时间:2018-01-22 08:44:17

标签: apache-spark collections mapreduce set reduce

我有一组集合,每个集合包含许多项目。我想使用Spark检索所有对集合和元素,其中每个对在reduce处理之后将包含两个项目和两个集合 例如:

如果我有这个集合列表

Set A={1,2,3,4 }
Set B={1,2,4,5}
Set C= {2,3,5,6}

地图流程将是:

(A,1)
(A,2)
(A,3)
(B,1)
(B,2)
(B,4)
(B,5)
(C,2)
(C,3)
(C,5)
(C,6)

reduce之后的目标结果是:

(A B, 1 2) // since 1 2 exist in both A and B
(A B, 1 4)
(A B, 2 4)
(A C,2 3)
(B C,2 5) 
here (A B,1 3) not in the result because 1 3 not exists in B

你能帮助我在一个地图中解决Spark中的这个问题吗?一个用任何语言(Python,Scala或Java)减少函数?

1 个答案:

答案 0 :(得分:0)

让我们把这个问题分解成多个部分,我认为从输入列表到地图输出的转换是微不足道的。那么让我们从那里开始,

你有一个(String,int)列表,看起来像

("A", 1)
("A", 2)
....

让我们忘记你首先需要在结果集中使用2个整数元素,并且让我们解决从映射输出中获取任何2个键之间的交集。

您输入的结果看起来像

(AB, Set(1,2,4))
(BC, Set(2,5))
(AC, Set(2,3))

要做到这一点,首先,从映射的输出(mappedOutput)中提取所有键,这些键是(String,Int)的RDD,转换为set,并获取2个元素的所有组合(我在这里使用了一个愚蠢的方法,这样做的好方法就是使用组合生成器

val combinations = mappedOutput.map(x => x._1).collect.toSet
.subsets.filter(x => x.size == 2).toList
.map(x => x.mkString(""))

输出将是List(ab,ac,bc),这些组合代码将作为要加入的键。

将映射输出转换为set键列表(a,b,c)=>元素集

val step1 = mappedOutput.groupByKey().map(x => (x._1, x._2.toSet)) 

将组合代码作为第1步的关键

val step2 = step1.map(x => combinations.filter(y => y.contains(x._1)).map(y => (y, x))).flatMap(x => x)

输出将是(ab,(a,a中的元素集)),(ac,(a,a中的元素集))等。由于过滤器,我们不会附加组合代码bc来设置a

现在使用reduce

获取我想要的结果
val result = step2.reduceByKey((a, b) => ("", a.intersect(b))).map(x => (x._1, x._2._2))

所以我们现在有了我们想要的输出。剩下的就是将这个结果转换成你需要的结果,这很简单。

val transformed = result.map(x => x._2.subsets.filter(x => x.size == 2).map(y => (x._1, y.mkString(" ")))).flatMap(x => x)

结束:)