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>
答案 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的迭代count
和take
动作导致笛卡尔+滤波的时间效率可能较低,但由于它仅计算{{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)))