我可以找到许多设置生成器最大尺寸的示例,但是如何生成最小和最大长度之间的列表?
生成器的一个巧妙属性是它们是可组合的,因此您可以简单地使用
listOfN
生成器来组合列表长度的生成器。
for {
numElems <- Gen.choose(5, 12)
elems <- Gen.listOfN(numElems, elemGenerator)
} yield elems
我在这里唤醒鬼魂,但万一有人出现:
根据我对已接受答案的评论,该解决方案随机决定 5 到 12 之间的最大长度,但在这种情况下,生成列表的实际大小仍然可以是 0(零)或低于 5 的任何值。
我认为以下内容符合OP所描述的内容:
Gen
.listOfN(12, elemGenerator)
.suchThat(_.size >= 5)
如果有一个 API 可以方便地生成这个,或者说一个精确大小的列表,那就太酷了,
N
。
更新(2022/12/22)...因为我意识到我从未真正回答过OP的问题(并由最近的评论提示):
def listOf[E](min: Int, max: Int, factor: Int = 4, retries: Int = 10000)(implicit gen: Gen[E]): Gen[List[E]] = for {
size <- Gen.choose(min, max)
list <- Gen.listOfN(factor * size, gen).retryUntil(_.size >= min, retries).flatMap(_.take(size))
} yield list
factor
是为了增加在 10,000 尝试(ScalaCheck 的默认值)内生成大于大小min
的列表的可能性;也许太大的 factor
会偏离 min
大小的列表。
或者,如果您喜欢猫和朋友 (cats-scalacheck):
def listOf[E](min: Int, max: Int)(implicit gen: Gen[E]): Gen[List[E]] = for {
size <- Gen.choose(min, max)
list <- List.fill(size)(gen).sequence
} yield list
我无法证明 cats-scalacheck 中发生了什么;也许他们也使用
suchThat
或 retryUntil
。