假设我想构造一个BitSet,其中包含从0到n的所有整数,满足某个谓词f: Int => Boolean
。
我可以写点像
BitSet((0 until n):_*).filter(f)
当然有效。但感觉效率相当低!我打算在一个非常紧凑的循环中做这个,并希望提出更有效的方法。
答案 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
}