最快的方法来检查scala中的范围列表中的整数列表?

时间:2014-08-20 16:30:56

标签: list scala intervals scala-collections

我有一个整数列表,我需要找出它所属的范围。我有一个范围列表,最大可能是2到15的范围。目前对于每个整数,我检查范围列表并找到它的位置。但是这需要花费很多时间,因为我需要检查的整数列表包括几千个。

//list of integers
val numList : List[(Int,Int)] = List((1,4),(6,20),(8,15),(9,15),(23,27),(21,25))

//list of ranges
val  rangesList:List[(Int,Int)] = List((1,5),(5,10),(15,30))

def checkRegions(numPos:(Int,Int),posList:List[(Int,Int)]){
val loop = new Breaks()
loop.breakable {
  for (va <- 0 until posList.length) {
    if (numPos._1 >= posList(va)._1 && numPos._2 <= (posList(va)._2)) {
      //i save "va"
      loop.break()
    }
  }
}

}

目前,对于numList中的每个整数,我都会通过rangesList查找其范围并保存其范围位置。有没有更快/更好的方法解决这个问题?

更新:它实际上是一个与范围列表进行比较的元组列表。

2 个答案:

答案 0 :(得分:2)

首先,在apply上使用List是有问题的,因为它需要线性运行时间。

List(1,2,3)(2)必须遍历整个列表才能最终获得索引2的最后一个元素。

如果您希望代码高效,您应该找到解决方法或选择其他数据结构。像IndexedSeq这样的数据结构具有恒定的时间索引。

你应该避免breaks,据我所知,它可以通过例外工作,这不是一个好习惯。总有办法解决它。

您可以这样做:

val numList : List[(Int,Int)] = List((1,4),(6,20),(8,15),(9,15),(23,27),(21,25))
val rangeList:List[(Int,Int)] = List((1,5),(5,10),(15,30))

def getRegions(numList: List[(Int,Int)], rangeList:List[(Int,Int)]) = {
  val indexedRangeList = rangeList.zipWithIndex 
  numList.map{case (a,b) => indexedRangeList
    .find{case ((min, max), index) => a >= min && b <= max}.fold(-1)(_._2)}
}

并像这样使用它:

getRegions(numList, rangeList)
//yields List(0, -1, -1, -1, 2, 2)

当没有范围匹配时,我选择产生-1。关键是你事先用索引压缩范围。因此,我们知道每个范围,该范围的索引是什么,并且从不使用apply

如果您使用此方法让索引再次通过apply访问rangeList中的范围,则应考虑更改为IndexedSeq

当数字范围变大时,apply当然只会很昂贵。如果你提到它只有2-15,那就没问题了。我只想给你一般的想法。

答案 1 :(得分:2)

一种方法包括使用带有par的并行集合,以及indexWhere,它提供包含条件的集合中第一项的索引。

为了便于阅读,请考虑使用此谓词来检查区间包含,

def isIn( n: (Int,Int), r: (Int,Int) ) = (r._1 <= n._1 && n._2 <= r._2)

因此,

val indexes = numList.par.map {n => rangesList.indexWhere(r => isIn(n,r))}
indexes: ParVector(0, -1, -1, -1, 2, 2)

为每个数字提供包含它的范围集合中的索引。值-1表示条件不成立。

要将数字与范围索引相关联,请考虑这一点,

numList zip indexes
res: List(((1,4),  0), ((6,20),-1), ((8,15),-1), 
          ((9,15),-1), ((23,27),2), ((21,25),2))

并行集合可能比非并行集合更有效,可以对非常大量的项目执行计算。