在谓词中构建Scala中的BitSet?

时间:2013-03-14 22:48:50

标签: scala bitset

假设我想构造一个BitSet,其中包含从0到n的所有整数,满足某个谓词f: Int => Boolean

我可以写点像

BitSet((0 until n):_*).filter(f)

当然有效。但感觉效率相当低!我打算在一个非常紧凑的循环中做这个,并希望提出更有效的方法。

3 个答案:

答案 0 :(得分:2)

这是我现在能想到的最好的

BitSet((0 until n).view.filter(f):_*)

视图部分使filter方法变得懒惰。这确保了当从给定序列创建BitSet时,它将在运行时进行过滤。在创建第一个建议后,您的原始建议会创建一个新的BitSet

答案 1 :(得分:1)

我认为最有效的“功能”方式是使用foldLeft

(1 to 5).foldLeft(BitSet())((s,i) => if (f(i)) s + i else s)

它不会创建中间集合,而是在过滤时从头开始构建集合。

我认为首先要使用breakOut,但它不适用于filter

scala> val set: BitSet = (0 until 10).filter(f)(collection.breakOut)
<console>:11: error: polymorphic expression cannot be instantiated to expected type;
 found   : [From, T, To]scala.collection.generic.CanBuildFrom[From,T,To]
 required: Int
       val set: BitSet = (0 until 10).filter(f)(collection.breakOut)
                                                           ^

scala> val set: BitSet = (0 until 10).map(_+1)(collection.breakOut)
set: scala.collection.immutable.BitSet = BitSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

breakOut也不会创建中间集合,但由于filter没有第二个参数列表,因此无法正常工作。

答案 2 :(得分:1)

如果性能确实是您最关心的问题,那么最佳选择可能是使用mutable.BitSet和while循环,然后在结果上调用toImmutable

val bitSet = {
  val tmp = new scala.collection.mutable.BitSet(n)
  var i = 0;
  while (i < n) {
    if (f(i)) {
      tmp += i
    }
    i = i + 1
  }
  tmp.toImmutable
}