我有一组集合,每个集合包含许多项目。我想使用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)减少函数?
答案 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)
结束:)