Reputation: 47
I am fairly new to ScalaCheck and somehow I want to generate a list of distinct values (i.e. a set). With my approach the values are not unique.
val valueList: Gen[List[Int]] = Gen.ListOf(Arbitrary.arbitrary[Int])
What are the possible ways to create a list with unique values/a set? Maybe with using suchThat
or distinct
?
Upvotes: 1
Views: 879
Reputation: 467
Following up on what Levi Ramsey said, you might want to check out https://github.com/rallyhealth/scalacheck-ops for the ability to generate sets of a specific size.
import org.scalacheck.Arbitrary.arbitrary
import org.scalacheck.Gen
import org.scalacheck.ops._
Gen.setOfN(5, arbitrary[Int]).map(_.toVector)
Upvotes: 1
Reputation: 20541
Crude but effective:
Gen.listOf(Arbitrary.arbitrary[Int]).map(_.toSet)
If you wanted a set of a particular size, you could do something like
def setOfN[A](n: Int, gen: Gen[A]): Gen[Set[A]] =
Gen.listOfN(n, gen).flatMap { lst =>
val set = lst.toSet
if (set.size == n) Gen.const(set)
else if (set.size > n) Gen.const(set.take(n))
else setOfN(n - set.size, gen.retryUntil(x => !set(x))).flatMap(_ ++ set)
}
(It's worth noting that retryUntil can be fragile, especially as n grows relative to the number of commonly generated values (e.g. for Int
Scalacheck generates 0, +/- 1, etc. fairly frequently))
And of course, since there's an org.scalacheck.util.Buildable
instance for Set
Gen.containerOf[Set, Int](Arbitrary.arbitrary[Int])
Upvotes: 5