Как разбить строку текста и добавить эту строку к каждому элементу в Scala / Spark - PullRequest
0 голосов
/ 26 апреля 2019

Учитывая строку типа «Яблоко упало с дерева», как мне разбить его так, чтобы к каждому слову добавлялась строка текста, чтобы я получал СДР из строк, которые выглядели бы так:

"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 со строками, которые представляют каждую строку текста.FlatMap разделяет эти строки на "", и, поскольку это flatMap, мы получаем один массив, в отличие от группы массивов.Пожалуйста, поправьте меня, если я ошибаюсь или неправильно говорю.

1 Ответ

0 голосов
/ 26 апреля 2019

У меня нет искры под рукой, поэтому я не могу подтвердить прямо сейчас, но, глядя на код и сообщение об ошибке, скорее всего, это просто foreach.

Итак, быстрое исправление будет (вероятно)заменить последнюю строку на

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

Объяснение:

  • line.split дает вам Array[String], который, я считаю, является экземпляром Traversable[String]
  • foreach применяет функцию к каждому элементу, но возвращает Unit - это означает, что при вызове нет возвращаемого значения (на практике это единственный экземпляр типа Unit, но если это поможет, вы можете подуматьэто void в терминах Java)
  • map также применяет функцию к каждому элементу, но возвращает новый Traversable (потенциально другого конкретного типа), который содержит обновленные элементы.
  • Наконец, flatMap - это метод, который по существу объединяет map и flatten - т.е. он принимает функцию, которая принимает элемент и возвращает Traversable[OtherType], применяет функцию к каждому элементу, а затем "выравнивает"«результирующее Traversable[Traversable[OtherType]] путем конкатенации внутреннего проходимогоs.Таким образом, вам нужно дать String => Traversable[String], но вы передаете String => Unit

Более подробную информацию см. В Scala Проходные документы .

Подобный кодв простом списке строк:

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более или менее похож на final.В вашем примере кода вы можете смело заменить var s на val s.

...