我有
形式的RDDcurRdd
res10: org.apache.spark.rdd.RDD[(scala.collection.immutable.Vector[(Int, Int)], Int)] = ShuffledRDD[102]
curRdd.collect()
会产生以下结果。
Array((Vector((5,2)),1), (Vector((1,1)),2), (Vector((1,1), (5,2)),2))
此处键:整数对的矢量和值:count
现在,我希望通过渗透计数将其转换为相同格式RDD[(scala.collection.immutable.Vector[(Int, Int)], Int)]
的另一个RDD。
(Vector((1,1), (5,2)),2))
(Vector((5,2)),1)
会将其计数为2的任何键,其中(Vector((5,2)),3)
成为(Vector((5,2)),3), (Vector((1,1)),4), (Vector((1,1), (5,2)),2)
。
对于上面的示例,我们的新RDD将具有
{{1}}
我如何实现这一目标?请帮助。
答案 0 :(得分:2)
首先,您可以为subsets
引入Seq
操作:
implicit class SubSetsOps[T](val elems: Seq[T]) extends AnyVal {
def subsets: Vector[Seq[T]] = elems match {
case Seq() => Vector(elems)
case elem +: rest => {
val recur = rest.subsets
recur ++ recur.map(elem +: _)
}
}
}
empty
子集将始终是结果向量中的第一个元素,因此您可以使用.tail
现在您的任务非常明显 map
- reduce
,其中 flatMap
- reduceByKey
就RDD
:
val result = curRdd
.flatMap { case (keys, count) => keys.subsets.tail.map(_ -> count) }
.reduceByKey(_ + _)
此实现可能会在结果中引入新的集合,如果您只想选择原始集合中显示的那些集合,您可以将结果与原始集合结合:
val result = curRdd
.flatMap { case (keys, count) => keys.subsets.tail.map(_ -> count) }
.reduceByKey(_ + _)
.join(curRdd map identity[(Seq[(Int, Int)], Int)])
.map { case (key, (v, _)) => (key, v) }
请注意,需要map identity
步骤才能将原始Vector[_]
中的密钥类型从Seq[_]
转换为RDD
。您可以修改SubSetsOps
定义,用Seq[T]
替换所有Vector[T]
或更改定义(硬编码scala.collection
)方式:
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class SubSetsOps[T, F[e] <: SeqLike[e, F[e]]](val elems: F[T]) extends AnyVal {
def subsets(implicit cbf: CanBuildFrom[F[T], T, F[T]]): Vector[F[T]] = elems match {
case Seq() => Vector(elems)
case elem +: rest => {
val recur = rest.subsets
recur ++ recur.map(elem +: _)
}
}
}