【问题标题】:Initializing a scala BitSet from a range从范围初始化 Scala BitSet
【发布时间】:2011-06-16 04:05:28
【问题描述】:

我想初始化一个 scala BitSet 以包含从 1 到 N 的整数。以下方法可行,但我正在寻找更好的解决方案:

var s = BitSet.empty ++ (1 to n)

我希望我能做这样的事情:

var s:BitSet = (1 to n).toSet

...但这会导致错误:

error: polymorphic expression cannot be instantiated to expected type;
  found   : [B >: Int]scala.collection.immutable.Set[B]
  required: scala.collection.immutable.BitSet

我是否遗漏了一些明显的东西?

【问题讨论】:

  • 我喜欢第一个解决方案。它在下面的工作方式也令人印象深刻。

标签: scala


【解决方案1】:

这就是breakOut 的用途:

val s: BitSet = (1 to n).map(identity)(breakOut)

查看this question了解breakOut的内部工作原理。

另一种解决方案是使用BitSet的构造函数:

val s = BitSet((1 to n): _*)

: _* 告诉编译器您想使用 Range 作为重复参数。

因为breakOut 看起来很难看,所以您可以使用 pimp-my-library 模式生成更好看的代码(如 here 所述):

val s = (1 to n).to[BitSet]

【讨论】:

    【解决方案2】:

    深入Scala源码,toBitSet的定义在TraversibleOnce.scala中:

    /** Converts this $coll to a set.
     *  $willNotTerminateInf
     *  @return      a set containing all elements of this $coll.
     */
    def toSet[B >: A]: immutable.Set[B] = immutable.Set() ++ self
    

    所以,有趣的是,toSet 的 Scala 实现基本上只是在普通 Set 的情况下在幕后执行您的第一个解决方案。如果你真的更喜欢你为 BitSet 建议的第二种语法,那么你可以使用隐式类型转换来自己动手:

    class BitSetConvertible(t: TraversableOnce[Int]) {
      def toBitSet = BitSet.empty ++ t
    }
    
    implicit def asBitSetConvertible(t: TraversableOnce[Int]) = new BitSetConvertible(t)
    

    有了这些,您现在可以做出如下声明:

    val s = 1 to 10 toBitSet
    

    【讨论】:

      猜你喜欢
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多