如何根据特定逻辑从另一个RDD生成新的RDD

时间:2015-10-26 01:24:00

标签: apache-spark

我是Spark的新生。我有一个问题,但我不知道如何解决它。我在RDD中的数据如下:

(1,{A,B,C,D})
(2,{E,F,G})
......

我知道RDD是不可变的,但是,我想将我的RDD转换为一个新的RDD,如下所示:

11 A,B
12 B,C
13 C,D
21 E,F
22 F,G
......

如何生成新密钥并提取相邻元素?

1 个答案:

答案 0 :(得分:1)

假设您的收藏类似于List,您可以执行以下操作:

val rdd2 = rdd1.flatMap { case (key, values) => 
  for (value <- values.sliding(2).zipWithIndex) 
    yield (key.toString + value._2, value._1) 
}

我们在这里做的是遍历列表中的值,在元素上应用大小为2的滑动窗口,用整数索引压缩元素,最后输出由附加的原始索引键入的元组列表列表索引(其值是滑动元素)。我们还在这里使用flatMap,以便将结果展平为自己的记录。

在spark-shell中运行时,我在您的示例中看到以下输出:

scala> val rdd1 = sc.parallelize(Array((1,List("A","B","C","D")), (2,List("E","F","G"))))
rdd1: org.apache.spark.rdd.RDD[(Int, List[String])] = ParallelCollectionRDD[0] at parallelize at <console>:21

scala> val rdd2 = rdd1.flatMap { case (key, values) => for (value <- values.sliding(2).zipWithIndex) yield (key.toString + value._2, value._1) }
rdd2: org.apache.spark.rdd.RDD[(String, Seq[String])] = MapPartitionsRDD[1] at flatMap at <console>:23

scala> rdd2.foreach(println)
...
(10,List(A, B))
(11,List(B, C))
(12,List(C, D))
(20,List(E, F))
(21,List(F, G))

这样做的一个注意事项是,如果您有11个或更多元素,则输出键(例如1011)将具有3位数字。例如,对于输入键1,您将在第11个元素上有一个输出键110。不确定这是否适合您的用例,但它似乎是您的请求的合理扩展。根据您的输出密钥方案,我实际上会建议一些不同的东西(比如可能在密钥和元素之间添加连字符?)。这样可以防止以后发生冲突,因为您会在两个密钥中看到2-1021-0而不是210