3

整数のセットをビットベクトル(その整数のセットの特性関数になる)で表現し、このセットに対してビット単位の演算を実行できるようにする方法を探しています。

当初、scalaのBitSetが理想的な候補になると思いました。ただし、ドキュメント1によると、BitSetはシフト操作をサポートしていないようです。さらに調査したところ、関連するJavaBitSet実装はシフト操作もサポートしていないことがわかりました2

シフト操作をサポートする独自のBitSetクラスを実装する唯一のオプションが残っていますか?さらに、 3で与えられた説明によると、ScalaのBitSet実装でシフト操作をサポートすることはそれほど難しいことではないように聞こえますか、それとも私はここで何かを誤解しましたか?

前もって感謝します。

4

2 に答える 2

6

新しい機能を後付けする必要に直面したときの通常のトリックは、「PimpMyLibrary」パターンです。追加された操作を実行することを目的とした専用タイプにBitSetを暗黙的に変換します。

class ShiftableBitSet(bs: BitSet) {
  def shiftLeft(n: Int): BitSet = ... //impl goes here
}

implicit def bitsetIsShiftable(bs: BitSet) = new ShiftableBitSet(bs)

val sample = BitSet(1,2,3,5,7,9)
val shifted = sample.shiftLeft(2)

任意shiftLeftの名前と任意の引数に変更します。

アップデート

If you know for certain that you'll have an immutable BitSet, then a (slightly hacky) approach to access the raw underlying array is to pattern match. Not too painful either, as there are only 3 possible concrete subclasses for an immutable BitSet:

import collection.immutable.BitSet
val bitSet = BitSet(1,2,3)
bitSet match {
  case bs: BitSet.BitSet1 => Array(bs.elems)
  case bs: BitSet.BitSetN => bs.elems 
  case _ => error("unusable BitSet")
}

Annoyingly, the elems1 param to BitSet2 isn't a val, and the elems param to a mutable BitSet is marked protected. So it's not perfect, but should do the trick if your set is non-trivial and immutable. For the trivial cases, "normal" access to the set won't be too expensive.

And yes, this technique would be used within the wrapper as described above.

于 2011-09-07T20:28:58.683 に答える
-3

You can just use map, for example to shift to left by 4 positions:

import collection.immutable.BitSet
val bitSet = BitSet(1,2,3)
bitSet map (_ + 4)
于 2015-12-25T12:53:41.740 に答える