scala – 使用大数据缓慢IO
发布时间:2020-12-16 09:05:32 所属栏目:安全 来源:网络整理
导读:我正在努力寻找一种更好的方法,因为它可能需要数年才能计算出来!我需要计算一个太大而不适合内存的映射,所以我试图按如下方式使用IO. 我有一个包含Ints列表的文件,大约有100万个.我有另一个文件,其中包含有关我(500,000)文档集的数据.我需要计算一个函数,对
我正在努力寻找一种更好的方法,因为它可能需要数年才能计算出来!我需要计算一个太大而不适合内存的映射,所以我试图按如下方式使用IO.
我有一个包含Ints列表的文件,大约有100万个.我有另一个文件,其中包含有关我(500,000)文档集的数据.我需要计算一个函数,对于第一个文件中的每个Int,它出现的文档数量(第二个中的行数).让我举个例子: 文件1: -1 1 2 etc... 文件2: E01JY3-615,CR93E-177,[-1 -> 2,1 -> 1,2 -> 2,3 -> 2,4 -> 2,8 -> 2,... // truncated for brevity] E01JY3-615,[1 -> 2,5 -> 2,... // truncated for brevity] etc... 这是我到目前为止所尝试的 def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) { val p = new java.io.PrintWriter(new BufferedWriter((new FileWriter(f)))) try { op(p) } finally { p.close() } } def binarySearch(array: Array[String],word: Int):Boolean = array match { case Array() => false case xs => if (array(array.size/2).split("->")(0).trim().toInt == word) { return true } else if (array(array.size/2).split("->")(0).trim().toInt > word){ return binarySearch(array.take(array.size/2),word) } else { return binarySearch(array.drop(array.size/2 + 1),word) } } var v = Source.fromFile("vocabulary.csv").getLines() printToFile(new File("idf.csv"))(out => { v.foreach(word =>{ var docCount: Int = 0 val s = Source.fromFile("documents.csv").getLines() s.foreach(line => { val split = line.split("[") val fpStr = split(1).init docCount = if (binarySearch(fpStr.split(","),word.trim().toInt)) docCount + 1 else docCount }) val output = word + "," + math.log10(500448 / (docCount + 1)) out.println(output) println(output) }) }) 必须有更快的方法来做到这一点,任何人都可以想到一种方式吗? 解决方法
根据我对您的代码的理解,您试图在文档列表中查找字典中的每个单词.
因此,您正在进行N * M比较,其中N是单词的数量(在带有整数的字典中),M是文档列表中的文档数.实例化您的值,您正在尝试计算10 ^ 6 * 5 * 10 ^ 5比较,即5 * 10 ^ 11.不可行的. 为什么不创建一个可变映射,将字典中的所有整数作为键(内存中的1000000个int大约是我的测量值的3.8M)并且仅通过文档列表一次,其中为每个文档提取整数并递增相应的计数地图中的值(整数是关键字). 像这样的东西: import collection.mutable.Map import scala.util.Random._ val maxValue = 1000000 val documents = collection.mutable.Map[String,List[(Int,Int)]]() // util function just to insert fake input; disregard def provideRandom(key:String) ={ (1 to nextInt(4)).foreach(_ => documents.put(key,(nextInt(maxValue),nextInt(maxValue)) :: documents.getOrElse(key,Nil)))} // inserting fake documents into our fake Document map (1 to 500000).foreach(_ => {val key = nextString(5); provideRandom(key)}) // word count map val wCount = collection.mutable.Map[Int,Int]() // Counting the numbers and incrementing them in the map documents.foreach(doc => doc._2.foreach(k => wCount.put(k._1,(wCount.getOrElse(k._1,0)+1)))) scala> wCount res5: scala.collection.mutable.Map[Int,Int] = Map(188858 -> 1,178569 -> 2,437576 -> 2,660074 -> 2,271888 -> 2,721076 -> 1,577416 -> 1,77760 -> 2,67471 -> 1,804106 -> 2,185283 -> 1,41623 -> 1,943946 -> 1,778258 -> 2... 结果是一个映射,其键是dict中的数字,值是它在文档列表中出现的次数 这是过于简单的 >我不验证字典中是否存在数字,尽管您只需要使用值初始化地图,然后在最终地图中增加该值(如果它具有该键); 这样您只需通过一次文档,这使任务再次可行. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |