Spark:从RDD [X]生成所有可能组合的RDD [(X,X)]

时间:2014-10-24 23:51:10

标签: scala apache-spark

Spark是否有可能实施' .combinations'来自scala集合的函数?

   /** Iterates over combinations.
   *
   *  @return   An Iterator which traverses the possible n-element combinations of this $coll.
   *  @example  `"abbbc".combinations(2) = Iterator(ab, ac, bb, bc)`
   */

例如,对于size = 2的组合,如何从RDD [X]到RDD [List [X]]或RDD [(X,X)]。并假设RDD中的所有值都是唯一的。< / p>

4 个答案:

答案 0 :(得分:28)

笛卡儿积和两种不同的东西,笛卡尔积将创建一个大小为rdd.size() ^ 2的RDD,组合将创建一个大小为rdd.size() choose 2的RDD

val rdd = sc.parallelize(1 to 5)
val combinations = rdd.cartesian(rdd).filter{ case (a,b) => a < b }`.
combinations.collect()

请注意,只有在列表元素上定义了排序时才会有效,因为我们使用<。这个只适用于选择两个,但可以通过确保序列中所有a和b的关系a < b轻松扩展

答案 1 :(得分:3)

Spark RDD使用cartesian转换本身支持此功能。

e.g:

val rdd = sc.parallelize(1 to 5)
val cartesian = rdd.cartesian(rdd)
cartesian.collect

Array[(Int, Int)] = Array((1,1), (1,2), (1,3), (1,4), (1,5), 
(2,1), (2,2), (2,3), (2,4), (2,5), 
(3,1), (3,2), (3,3), (3,4), (3,5), 
(4,1), (4,2), (4,3), (4,4), (4,5), 
(5,1), (5,2), (5,3), (5,4), (5,5))

答案 2 :(得分:3)

正如所讨论的,cartesian将为您提供RDD的笛卡尔积的n ^ 2个元素。 该算法首先计算RDD的组合(n,2),而不必首先计算n ^ 2个元素:(使用String作为类型,推广到类型T需要一些带有classtags的管道,这会掩盖这里的目的)

由于强制计算RDD的迭代counttake动作导致笛卡尔+滤波的时间效率可能较低,但由于它仅计算{{1} }元素而不是笛卡尔积的C(n,2) = n!/(2*(n-2))! = (n*(n-1)/2)

n^2

答案 3 :(得分:2)

这将创建所有组合(n,2)并适用于任何RDD,而无需对RDD元素进行任何排序。

val rddWithIndex = rdd.zipWithIndex
rddWithIndex.cartesian(rddWithIndex).filter{case(a, b) => a._2 < b._2}.map{case(a, b) => (a._1, b._1)}

a._2和b._2是指数,而a._1和b._1是原始RDD的元素。

示例:

请注意,这里的地图上没有定义排序。

val m1 = Map('a' -> 1, 'b' -> 2)
val m2 = Map('c' -> 3, 'a' -> 4)
val m3 = Map('e' -> 5, 'c' -> 6, 'b' -> 7)
val rdd = sc.makeRDD(Array(m1, m2, m3))
val rddWithIndex = rdd.zipWithIndex
rddWithIndex.cartesian(rddWithIndex).filter{case(a, b) => a._2 < b._2}.map{case(a, b) => (a._1, b._1)}.collect

输出:

Array((Map(a -> 1, b -> 2),Map(c -> 3, a -> 4)), (Map(a -> 1, b -> 2),Map(e -> 5, c -> 6, b -> 7)), (Map(c -> 3, a -> 4),Map(e -> 5, c -> 6, b -> 7)))