加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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中的数字,值是它在文档列表中出现的次数

这是过于简单的

>我不验证字典中是否存在数字,尽管您只需要使用值初始化地图,然后在最终地图中增加该值(如果它具有该键);
>我不做IO,这加速了整个事情

这样您只需通过一次文档,这使任务再次可行.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读