Apache Spark的RDD根据特定大小进行拆分

时间:2016-03-03 02:21:20

标签: scala apache-spark rdd

我正在尝试从文本文件中读取字符串,但我想根据特定大小限制每一行。例如;

这是我代表该文件。

  

AAAAA \ nbbb \ nccccc

当尝试通过sc.textFile读取此文件时,RDD会出现此文件。

scala> val rdd = sc.textFile("textFile")
scala> rdd.collect
res1: Array[String] = Array(aaaaa, bbb, ccccc)

但是我想限制这个RDD的大小。例如,如果限制为3,那么我应该像这样。

Array[String] = Array(aaa, aab, bbc, ccc, c)

这样做的最佳表现方式是什么?

2 个答案:

答案 0 :(得分:2)

不是一个特别有效的解决方案(也不是很糟糕),但你可以这样做:

val pairs = rdd
  .flatMap(x => x)  // Flatten
  .zipWithIndex  // Add indices
  .keyBy(_._2 / 3)  // Key by index / n

// We'll use a range partitioner to minimize the shuffle 
val partitioner = new RangePartitioner(pairs.partitions.size, pairs)

pairs
  .groupByKey(partitioner)  // group
  // Sort, drop index, concat
  .mapValues(_.toSeq.sortBy(_._2).map(_._1).mkString("")) 
  .sortByKey()
  .values

可以通过传递显式填充分区所需的数据来避免混乱,但需要花费一些精力进行编码。请参阅我对Partition RDD into tuples of length n的回答。

如果您可以在分区边界上接受一些未对齐的记录,那么带分组的简单mapPartitions应该以更低的成本完成这一操作:

rdd.mapPartitions(_.flatMap(x => x).grouped(3).map(_.mkString("")))

也可以使用滑动RDD:

rdd.flatMap(x => x).sliding(3, 3).map(_.mkString(""))

答案 1 :(得分:0)

无论如何,您需要阅读所有数据。除了映射每条线并修剪它之外,你可以做的不多。

rdd.map(line => line.take(3)).collect()