在 Scala 中将 BitSet 设置为 Set[Int] 或反之亦然
BitSet to Set[Int] or vice versa in Scala
我有一个使用 BitSet 的库,我需要更改 Set[Int] 类型的数据才能使用该库。
我想到的是使用 .toSeq:_*
操作,但我不确定这是从 BitSet 转换为 Set[Int] 还是相反的有效方法。
scala> BitSet(Set(1,2,3).toSeq:_*)
res55: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
scala> Set(BitSet(1,2,3).toSeq:_*)
res56: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
有没有更好的方法?
Scala 的 Set
层次结构有点奇怪,但是 BitSet
的超类型是 Set[Int]
,所以你可以简单地传递一个 BitSet
到一个需要 Set[Int]
等的方法
这似乎不是这种情况,因为默认情况下您获得的 Set
是 immutable.Set
(在 scala.collection
下),而您使用的库可能是使用 scala.collection
下的 BitSet
,而不是 immutable.BitSet
。在您的示例代码中情况并非如此,所有内容都在 immutable
中,但我不确定它的简化程度。
如果您有幸使用 immutable
包的 Set
和 BitSet
版本,则 BitSet
到 Set
方向微不足道:
scala> import scala.collection.immutable.BitSet
import scala.collection.immutable.BitSet
scala> val bs = BitSet(0, 100, 200)
bs: scala.collection.immutable.BitSet = BitSet(0, 100, 200)
scala> def takesSet(s: Set[Int]): Int = s.size
takesSet: (s: Set[Int])Int
scala> takesSet(bs)
res0: Int = 3
如果你有 scala.collection.BitSet
,只需使用 toSet
:
scala> takesSet(scala.collection.BitSet(0, 100, 200).toSet)
res1: Int = 3
另外一个方向,你的版本没问题:
scala> val s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> BitSet(s.toSeq: _*)
res2: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
但同样值得注意的是,在许多情况下,您可以使用一些 CanBuildFrom
魔法来避免这种转换:
scala> val bs: BitSet = Set("1", "2", "3").map(_.toInt)(collection.breakOut)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
这会产生与以下相同的结果:
scala> val bs: BitSet = BitSet(Set("1", "2", "3").map(_.toInt).toSeq: _*)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
但是,collection.breakOut
参数告诉编译器使用 CanBuildFrom
类型的实例执行映射,而不是在 BitSet
之前构建中间集(和序列)class 将直接构造 BitSet
。以这种方式显式传递 CanBuildFrom
实例不仅适用于 map
,它也适用于 flatMap
、scanLeft
、++
和其他允许您更改元素类型的集合操作。
认为面向对象:BitSet
是一个Set[Int]
,你不需要做任何事情来将一个转换成另一个:
import scala.collection._
val set: Set[Int] = BitSet(1,2,3)
走另一条路更难,并且需要线性时间:
val bs: BitSet = BitSet(set.toStream:_*)
但是当你发现自己需要这种 "upconverting" 时,99% 的情况下它是糟糕设计的标志,应该改进以消除这种需要:特定 [= 的实现细节14=] 应该只对最初创建它的代码有影响,下游代码通常应该与实现无关。
我有一个使用 BitSet 的库,我需要更改 Set[Int] 类型的数据才能使用该库。
我想到的是使用 .toSeq:_*
操作,但我不确定这是从 BitSet 转换为 Set[Int] 还是相反的有效方法。
scala> BitSet(Set(1,2,3).toSeq:_*)
res55: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
scala> Set(BitSet(1,2,3).toSeq:_*)
res56: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
有没有更好的方法?
Scala 的 Set
层次结构有点奇怪,但是 BitSet
的超类型是 Set[Int]
,所以你可以简单地传递一个 BitSet
到一个需要 Set[Int]
等的方法
这似乎不是这种情况,因为默认情况下您获得的 Set
是 immutable.Set
(在 scala.collection
下),而您使用的库可能是使用 scala.collection
下的 BitSet
,而不是 immutable.BitSet
。在您的示例代码中情况并非如此,所有内容都在 immutable
中,但我不确定它的简化程度。
如果您有幸使用 immutable
包的 Set
和 BitSet
版本,则 BitSet
到 Set
方向微不足道:
scala> import scala.collection.immutable.BitSet
import scala.collection.immutable.BitSet
scala> val bs = BitSet(0, 100, 200)
bs: scala.collection.immutable.BitSet = BitSet(0, 100, 200)
scala> def takesSet(s: Set[Int]): Int = s.size
takesSet: (s: Set[Int])Int
scala> takesSet(bs)
res0: Int = 3
如果你有 scala.collection.BitSet
,只需使用 toSet
:
scala> takesSet(scala.collection.BitSet(0, 100, 200).toSet)
res1: Int = 3
另外一个方向,你的版本没问题:
scala> val s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> BitSet(s.toSeq: _*)
res2: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
但同样值得注意的是,在许多情况下,您可以使用一些 CanBuildFrom
魔法来避免这种转换:
scala> val bs: BitSet = Set("1", "2", "3").map(_.toInt)(collection.breakOut)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
这会产生与以下相同的结果:
scala> val bs: BitSet = BitSet(Set("1", "2", "3").map(_.toInt).toSeq: _*)
bs: scala.collection.immutable.BitSet = BitSet(1, 2, 3)
但是,collection.breakOut
参数告诉编译器使用 CanBuildFrom
类型的实例执行映射,而不是在 BitSet
之前构建中间集(和序列)class 将直接构造 BitSet
。以这种方式显式传递 CanBuildFrom
实例不仅适用于 map
,它也适用于 flatMap
、scanLeft
、++
和其他允许您更改元素类型的集合操作。
认为面向对象:BitSet
是一个Set[Int]
,你不需要做任何事情来将一个转换成另一个:
import scala.collection._
val set: Set[Int] = BitSet(1,2,3)
走另一条路更难,并且需要线性时间:
val bs: BitSet = BitSet(set.toStream:_*)
但是当你发现自己需要这种 "upconverting" 时,99% 的情况下它是糟糕设计的标志,应该改进以消除这种需要:特定 [= 的实现细节14=] 应该只对最初创建它的代码有影响,下游代码通常应该与实现无关。