如何分割文本行并将该行附加到Scala / Spark

时间:2019-04-26 03:22:45

标签: arrays string scala apache-spark flatmap

给出一个像“苹果从树上掉下来”这样的字符串,我该如何分割它,以便每个单词都附加一行文字,这样我得到的字符串的RDD如下:

"The | The apple fell from a tree"
"apple | The apple fell from a tree"
"fell | The apple fell from a tree"
"from | The apple fell from a tree"
"a | The apple fell from a tree"
"tree | The apple fell from a tree"

这将使我能够跟踪单词的来源。

这是我写的(相关部分)

var inputPath = /path/to/file.txt // Some txt file
var input = sc.textFile(inputPath) // RDD of lines of text
var words = input.flatMap(line => line.split(" ").foreach(word => word.concat(" | " + line)) 

此代码示例不起作用,因为据我了解,您不能多次在flatMap中遍历吗?我相信我说Found: Unit Required: TraversableOnce[?]时遇到错误,我是Spark,Scala和函数式编程的新手。第一次编写scala时,我并不担心性能或最短的代码量。我只是希望某些工作而不必重新设计我的实现。我以后总是可以重构。

我知道textFile()给了我一个RDD,其中的Strings代表了文本的每一行。 flatMap用“”拆分这些行,由于它是flatMap,所以我们得到一个数组,而不是一堆数组。如果我错了,或者说话不正确,请纠正我。

1 个答案:

答案 0 :(得分:0)

我手头没有火花,因此无法立即确认,但查看代码和错误消息,很可能只是foreach

因此,快速解决方法(可能)是将最后一行替换为

input.flatMap(line => line.split(" ").map(word => word.concat(" | " + line))

说明:

  • line.split给您一个Array[String],我认为它是实例Traversable[String]
  • foreach对每个项目应用一个函数,但返回一个Unit-这意味着调用没有返回值(实际上,它是Unit类型的单例实例,但如果有帮助,您可以将其视为Java术语中的void
  • map还将函数应用于每个项目,但是返回包含更新后的项目的新Traversable(可能具有不同的具体类型)。
  • 最后,flatMap是一种本质上将mapflatten结合在一起的方法-即,它采用一个接受某项并返回Traversable[OtherType]的函数,将该函数应用于每个项目,然后通过串联内部可遍历来“展平”结果Traversable[Traversable[OtherType]]。因此,您需要给它String => Traversable[String],但您要传递String => Unit

有关更多信息,请参阅Scala Traversable docs

在普通字符串列表上的类似代码:

scala> List(
    "line1 word1 word2", 
    "line2 word3 word4"
)
    .flatMap(line => line.split(" ").map(word => s"$word | $line"))

res5: List[String] = List(
    line1 | line1 word1 word2,
    word1 | line1 word1 word2,
    word2 | line1 word1 word2,
    line2 | line2 word3 word4,
    word3 | line2 word3 word4,
    word4 | line2 word3 word4
)

顺便说一句,Scala鼓励不变性,因此您可能想使用val而不是var,除非您真的想重新分配值-val或多或少与{ {1}}。在您的代码示例中,可以肯定地用final替换var