在火花的rdd中找到最少的子集

时间:2018-03-03 13:53:33

标签: scala apache-spark

任何人都可以帮助我 我有一个像BitSets的RDD,如

Array[scala.collection.mutable.BitSet] = Array(BitSet(1, 2), BitSet(1, 7), BitSet(8, 9, 10, 11), BitSet(1, 2, 3, 4),BitSet(8,9,10),BitSet(1,2,3))

我想要(BitSet(1,2),BitSet(1,7),BitSet(8,9,10))的rdd 这是我需要最少的子集或BitSet,它不是任何BitSet的子集

说明: 这里(1,2),(1,2,3)(1,2,3,4) -----这里最少的子集是(1,2)(1,7)不是其他BitSet的子集---因此(1,7)也会出现在结果

1 个答案:

答案 0 :(得分:4)

使用聚合

可以解决此问题
val rdd = sc.parallelize(
  Seq(BitSet(1, 2),
      BitSet(1, 7),
      BitSet(8, 9, 10, 11),
      BitSet(1, 2, 3, 4),
      BitSet(8, 9, 10),
      BitSet(1, 2, 3)))
val result = rdd.aggregate(Seq[BitSet]())(accumulate, merge)
println(result)

输出:

List(BitSet(8, 9, 10), BitSet(1, 7), BitSet(1, 2))

accumulate是一个收集每个spark分区数据的函数

def accumulate(acc: Seq[BitSet], elem: BitSet): Seq[BitSet] = {
  val subsets = acc.filterNot(elem.subsetOf)
  if (notSuperSet(subsets)(elem)) elem +: subsets else subsets
}

merge结合了分区的结果

def merge(left: Seq[BitSet], right: Seq[BitSet]): Seq[BitSet] = {
  val leftSubsets = left.filter(notSuperSet(right))
  val rightSubsets = right.filter(notSuperSet(leftSubsets))
  leftSubsets ++ rightSubsets
}

和辅助函数notSuperSet,它是检查新集是否是其他集的超集的谓词

def notSuperSet(subsets: Seq[BitSet])(set: BitSet): Boolean =
  subsets.forall(!_.subsetOf(set))