簡體   English   中英

Spark Scala中向量的子集處理

[英]subsets manipulation on vectors in spark scala

我有以下形式的RDD curRdd

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))

此處 :整數對的向量和 :計數

現在,我想通過向下計數來將其轉換為RDD[(scala.collection.immutable.Vector[(Int, Int)], Int)]形式的另一個RDD。

也就是說(Vector((1,1), (5,2)),2))會將其2的計數貢獻給作為其子集的任何鍵,就像(Vector((5,2)),1)變成(Vector((5,2)),3)

對於上面的示例,我們的新RDD將具有

(Vector((5,2)),3), (Vector((1,1)),4), (Vector((1,1), (5,2)),2)

我該如何實現? 請幫助。

首先,您可以介紹Seq subsets操作:

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 - reduceflatMap - 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) }

請注意,在原始RDD需要map identity步驟才能將鍵類型從Vector[_]轉換為Seq[_] 相反,您可以修改SubSetsOps定義,用Vector[T]代替Seq[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 +: _)
      }
    }
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM