Scala BitSet и операции сдвига - PullRequest
2 голосов
/ 07 сентября 2011

Я ищу способ представления набора целых чисел с помощью битового вектора (который был бы характеристической функцией этого набора целых чисел) и возможность выполнять побитовые операции над этим набором.

Изначально я думал, что BitSet от Scala будет идеальным кандидатом.Однако, похоже, BitSet не поддерживает операции сдвига в соответствии с документацией 1 .После дальнейшего изучения я также обнаружил, что связанная реализация Java BitSet также не поддерживает операции сдвига 2 .

У меня осталась единственная возможность реализовать свой собственный класс BitSet, который поддерживает операции сдвига?Более того, в соответствии с описанием, приведенным в 3 , не представляется сложным поддерживать операции сдвига в реализации BitSet в Scala, или я что-то здесь неправильно понял?

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 08 сентября 2011

Обычной уловкой, когда возникает необходимость в переоснащении новой функциональности, является шаблон Pimp My Library.Неявно преобразуйте 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 на любое имя и аргумент, который вы предпочитаете.

ОБНОВЛЕНИЕ

Если вы точно знаете, что у вас будет неизменный BitSet, то (немного хакерский) подход к доступу к исходному массиву заключается в сопоставлении с образцом.Не слишком больно, поскольку есть только 3 возможных конкретных подкласса для неизменяемого 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")
}

Досадно, что параметр elems1 для BitSet2 не является val, а elems параметр для изменяемого BitSet помечен как защищенный.Так что он не идеален, но должен делать свое дело, если ваш сет нетривиален и неизменен.Для тривиальных случаев «нормальный» доступ к набору не будет слишком дорогим.

И да, этот метод будет использоваться в оболочке, как описано выше.

0 голосов
/ 25 декабря 2015

Вы можете просто использовать карту, например, для смещения влево на 4 позиции:

import collection.immutable.BitSet
val bitSet = BitSet(1,2,3)
bitSet map (_ + 4)
...