Scala 大文本文件
Posted
技术标签:
【中文标题】Scala 大文本文件【英文标题】:Scala Large Text file 【发布时间】:2013-01-07 15:26:03 【问题描述】:我是 Scala 编程的新手。
我必须处理 NLP 任务。
我在 Scala 中处理大型文本文件时遇到问题。
我已经将一个 100+ M.B 文件的整个文本读入内存(读入一个字符串)并且必须对其进行处理(我相信处理大型文本文件是自然语言处理中的一项常见任务)。
目标是计算给定字符串中唯一子字符串/单词的数量(即整个文件)。
我想在 List 对象中使用 "distinct" 方法,但是将字符串转换为列表 使用 ".split ”方法引发内存不足错误(“java.lang.OutOfMemoryError: Java heap space”错误)。
我想知道我是否可以在不使用 Scala 中使用字符串或正则表达式方法的列表的情况下完成这项任务?
【问题讨论】:
相关:***.com/questions/4255021/… 我试过了。逐行处理需要永远阅读。 虽然如果文件变得非常大,你肯定会遇到问题,但取决于你有多少内存,你可以尝试这里的一些建议来增加 JVM 可用的内存:***.com/questions/1441373/… 我使用 200+ MB 的文件进行了一些类似的工作来训练多层神经网络,而您必须提高可用的默认内存是不争的事实。我的笔记本电脑上有足够的内存,所以我通常为 JVM 使用以下命令行参数:-Xmx6g -XX:MaxPermSize=256m Raul,请举例说明您要解决的问题,即示例输入字符串和示例输出。例如"Twinkle twinkle little star" 作为输入必须给出 ("twinkle" -> 2, "little" -> 1, "star" -> 1) 作为输出。 【参考方案1】:Have a look at this blog 讨论您的问题以及解决问题的不同方法。
【讨论】:
这很有帮助。但为时已晚。 :)【参考方案2】:我假设,您的文件作为 List[String]
在内存中,并且列表中的每个条目都是文件的一行。
val textStream = text.toStream
val wordStream = textStream.view.flatMap(s => s.split(" "))
val distinctWordStream = wordStream.foldLeft(Stream.empty[String])((stream, string) =>
if (stream.contains(string)) stream else string #:: stream
)
首先,您创建一个 Stream,因此您不必处理整个 String。下一步是创建一个视图并对其进行映射,因此每个字符串中只有一个单词而不是一行。最后你逐字折叠结果。如果一个词被包含,它将被删除。除了折叠,你也可以使用这一行:
val wordSet = wordStream.toSet
此时获取不同单词的数量应该是微不足道的。您只需为 Set 调用 length
或 size
。
【讨论】:
【参考方案3】:默认的 JVM 堆大小肯定会增加。我非常怀疑使用拆分或任何其他基于 RE 的方法对于这么大的输入是否容易处理。同样,如果您将输入转换为List[Char]
以利用精彩的集合库,您将看到内存需求过度增加;尺寸膨胀将至少是十进制数量级。
鉴于相对简单的分解(由空格或标点符号分隔的单词),我认为可能需要一个更平淡的解决方案。强制迭代字符串的字符(但不是通过隐式转换为任何类型的Seq[Char]
)并找到单词,将它们转储到mutable.Set[String]
。一方面,这将消除重复。也许使用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
在 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)
【讨论】:
+1 平淡无奇 - 很酷的词,与解决实际问题有很好的关系;-) 您还可以在累积到Set
之前过滤掉停用词以及规范化大小写。这段代码有一个更大的问题,即缩略词(例如,“don't”)会被拆分(分成“don”和“t”)。警告程序员!以上是关于Scala 大文本文件的主要内容,如果未能解决你的问题,请参考以下文章