Scala大文本文件

gar*_*rak 2 string nlp scala

我是Scala编程的新手.

我必须处理NLP任务.

我在Scala中处理大型文本文件时遇到问题.

我已经将100多MB文件的整个文本读入内存(转换为字符串)并且必须处理它(我相信处理大型文本文件是自然语言处理中的常见任务).

目标是计算给定字符串(整个文件)中唯一子串/单词的数量.

我想在List对象中使用" distinct "方法,但是使用" .split "方法将字符串转换为列表会引发内存不足错误("java.lang.OutOfMemoryError:Java堆空间"错误).

我想知道如果不使用Scala中使用String或Regular Expression方法的列表,我是否可以完成此任务?

Ran*_*ulz 5

毫无疑问,默认的JVM堆大小可能必须增加.我非常怀疑使用拆分或任何其他基于RE的方法对于那么大的输入都是易处理的.同样,如果将输入转换为a List[Char]以利用精彩的集合库,您将会看到内存需求的过度增加; 规模膨胀将是最小的十进制数量级.

鉴于相对简单的分解(由空格或标点符号分隔的单词),我认为可能需要更平淡的解决方案.命令性地迭代字符串的字符(但不是通过隐式转换为任何类型Seq[Char])并找到单词,将它们转换为mutable.Set[String].一方面,这将消除重复.或许可以使用a Buffer[Char]来累积每个单词的字符,然后将它们变成String要添加到的单词中Set[String].

这是一个切口:

package rrs.scribble

object  BigTextNLP {
  def btWords(bt: String): collection.mutable.Set[String] = {
    val btLength = bt.length
    val wordBuffer = collection.mutable.Buffer[Char]()
    val wordSet = collection.mutable.Set[String]()

    /* Assuming btLength > 0 */

    import bt.{charAt => chr}
    import java.lang.Character.{isLetter => l}

    var inWord = l(chr(0))

    (0 until btLength) foreach { i =>
      val c = chr(i)
      val lc = l(c)

      if (inWord)
        if (lc)
          wordBuffer += c
        else {
          wordSet += wordBuffer.mkString
          wordBuffer.clear
          inWord = false
        }
      else
        if (lc) {
          inWord = true
          wordBuffer += c
        }
    }

    wordSet
  }
}
Run Code Online (Sandbox Code Playgroud)

在REPL中:

scala> import rrs.scribble.BigTextNLP._
import rrs.scribble.BigTextNLP._

scala> btWords("this is a sentence, maybe!")
res0: scala.collection.mutable.Set[String] = Set(this, maybe, sentence, is, a)
Run Code Online (Sandbox Code Playgroud)