我是Scala编程的新手.
我必须处理NLP任务.
我在Scala中处理大型文本文件时遇到问题.
我已经将100多MB文件的整个文本读入内存(转换为字符串)并且必须处理它(我相信处理大型文本文件是自然语言处理中的常见任务).
目标是计算给定字符串(整个文件)中唯一子串/单词的数量.
我想在List对象中使用" distinct "方法,但是使用" .split "方法将字符串转换为列表会引发内存不足错误("java.lang.OutOfMemoryError:Java堆空间"错误).
我想知道如果不使用Scala中使用String或Regular Expression方法的列表,我是否可以完成此任务?
毫无疑问,默认的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)