Я пытался создать перетасованные последовательности с помощью scalacheck. Scalacheck не предоставляет никакого генератора, чтобы сделать это напрямую, и я не смог найти простого ответа в Интернете. Немного подумав, ниже показано, как я это сделал. Я надеюсь, что другие найдут, если это будет полезно.
Как создать перетасованную последовательность с помощью ScalaCheck?
Ответы (2)
org.scalacheck.Gen.pick(n: Int, l: Iterable[T]): Gen[Seq[T]]
выбирает n
различных элемента из l
в случайном порядке. Позвоните pick
с помощью n = l.length
, и вы сгенерируете случайным образом
Вы можете использовать алгоритм перетасовки коллекций (например, в scala.util.Random), чтобы получить более четкое решение:
/**
* This represents a potential list shuffling. It
* acts as a pure function - when applied to the
* same list it always returns the same result
*/
class Shuffling(seed: Int) {
def apply[T](xs: Seq[T]): Seq[T] = {
val r = new scala.util.Random(seed)
r.shuffle(xs)
}
}
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen
val shufflingGen: Gen[Shuffling] = arbitrary[Int].map(new Shuffling(_))
Приведенный выше фрагмент определяет shuffling
— возможное изменение порядка списка. Он также определяет генератор, который предоставляет произвольные экземпляры для перетасовки. В следующем примере показано, как можно использовать перетасовку для переупорядочения диапазона целых чисел:
def shuffledRange(n: Int): Gen[Seq[Int]] = {
for {
shuffling <- shufflingGen
} yield shuffling(Range(0, n))
}
Может показаться странным добавить один уровень косвенности в виде класса Shuffling
— мы могли бы точно так же применить Random.shuffle
непосредственно к списку. Это связано с тем, что мы хотим избежать дополнительного источника случайности в дополнение к неявной рандомизации, которую Scalacheck уже выполняет в фоновом режиме — источник случайности при перетасовке исходит от генератора scalacheck.
Одним из преимуществ этого будет воспроизводимость сгенерированных случаев (всякий раз, когда Scalacheck будет поддерживать это).