【问题标题】:Scala Filter and Collect is slowScala过滤和收集很慢
【发布时间】:2016-08-09 10:14:11
【问题描述】:

我刚刚开始进行 Scala 开发,并尝试使用过滤器和收集从迭代器中过滤掉不必要的行。但是操作好像太慢了。

val src = Source.fromFile("/home/Documents/1987.csv") // 1.2 Million
val iter = src.getLines().map(_.split(":"))
val iter250 = iter.take(250000) // Only interested in the first 250,000

val intrestedIndices = range(1, 100000, 3).toSeq // This could be any order

val slicedData = iter250.zipWithIndex

// Takes 3 minutes
val firstCase = slicedData.collect { case (x, i) if intrestedIndices.contains(i) => x }.size 

// Takes 3 minutes
val secondCase = slicedData.filter(x => intrestedIndices.contains(x._2)).size 

// Takes 1 second
val thirdCase = slicedData.collect { case (x,i ) if i % 3 == 0 => x}.size   

似乎 intrestedIndices.contains(_) 部分在第一种和第二种情况下减慢了程序的速度。有没有其他方法可以加快这个过程。

【问题讨论】:

  • 您的第三个案例是正确的选择。为什么要使用 contains(_)?
  • 您在前两种情况下以线性时间迭代所有interestedIndices。使用Set 而不是Seq 来提高性能
  • @SergeyLagutin 换一个字符 :) val intrestedIndices = range(1, 100000, 3).toSe**t**
  • @Nyavro 在某些情况下顺序可能是随机的
  • @SergeyLagutin 谢谢,这对我想做的事情起到了作用

标签: performance scala optimization filter collect


【解决方案1】:

这个答案帮助解决了这个问题。

您在线性时间内迭代前两种情况下的所有感兴趣的索引。使用 Set 而不是 Seq 来提高性能——Sergey Lagutin

【讨论】:

    【解决方案2】:

    作为记录,这里有一个过滤(有序)索引序列的方法,不一定是等距的,而不需要在每一步扫描索引:

    def filterInteresting[T](it: Iterator[T], indices: Seq[Int]): Iterator[T] =
      it.zipWithIndex.scanLeft((indices, None: Option[T])) {
        case ((indices, _), (elem, index)) => indices match {
          case h :: t if h == index => (t, Some(elem))
          case l => (l, None)
        }
      }.map(_._2).flatten
    

    【讨论】:

      猜你喜欢
      • 2016-10-22
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多