Как я могу создать список из n уникальных элементов, выбранных из набора?

Как создать список из n уникальных значений (Gen[List[T]]) из набора значений (не генераторов) с помощью ScalaCheck? В этом сообщении вместо набора значений используется Gen[T]*, и я не могу его переписать чтобы заставить его работать.

ИЗМЕНИТЬ

По просьбе @Jubobs я теперь с позором показываю то, что пробовал до сих пор, показывая свой статус полного новичка в использовании ScalaCheck :-)

Я просто попытался заменить повторяющийся параметр gs: Gen[T] на Set в том, что @Eric написал в качестве решения здесь :

def permute[T](n: Int, gs: Set[T]): Gen[Seq[T]] = {
    val perm = Random.shuffle(gs.toList)
    for {
        is <- Gen.pick(n, 1 until gs.size)
        xs <- Gen.sequence[List[T], T](is.toList.map(perm(_)))
    } yield xs
}

но is.toList.map(perm(_)) было подчеркнуто красным, а IntelliJ IDEA сообщила мне, что "Сначала следует прочитать ScalaCheck API, прежде чем делать слепые (хотя и интуитивно понятные) пробы и ошибки", или, может быть, "Несоответствие типов, ожидаемое: Traversable [Gen[T]], настоящий List[T]", не помню.

Я также попробовал несколько других способов, большинство из которых я нахожу нелепыми (и, следовательно, не достойными публикации) в ретроспективе, причем самым наивным является использование решения @Eric (в остальном полезного и аккуратного) как есть:

val g = for (i1 <- Gen.choose(0, myList1.length - 1); 
  i2 <- Gen.choose(0, myList2.length - 1)) 
  yield new MyObject(myList1(i1), myList2(i2))
val pleaseNoDuplicatesPlease = permute(4, g, g, g, g, g)

После некоторого тестирования я увидел, что pleaseNoDuplicatesPlease на самом деле содержит дубликаты, и в этот момент я взвесил свои варианты: прочитать ScalaCheck API и понять намного больше, чем сейчас (что неизбежно и постепенно придет), или опубликовать свой вопрос в StackOverflow (после тщательного поиска подобных вопросов).


person bugfoot    schedule 06.05.2017    source источник
comment
[...] Кажется, я не могу переписать его так, чтобы он работал. Отредактируйте свой вопрос и покажите, что вы пробовали.   -  person jub0bs    schedule 07.05.2017


Ответы (1)


Gen.pick верно вверх по твоему переулку:

scala> import org.scalacheck.Gen
import org.scalacheck.Gen

scala> val set = Set(1,2,3,4,5,6)
set: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

scala> val myGen = Gen.pick(5, set).map { _.toList }
myGen: org.scalacheck.Gen[scala.collection.immutable.List[Int]] = org.scalacheck.Gen$$anon$3@78693eee

scala> myGen.sample
res0: Option[scala.collection.immutable.List[Int]] = Some(List(5, 6, 2, 3, 4))

scala> myGen.sample
res1: Option[scala.collection.immutable.List[Int] = Some(List(1, 6, 2, 3, 4))
person jub0bs    schedule 06.05.2017
comment
Есть еще несколько вариантов: github.com/rickynils/scalacheck/blob/master/src/main/scala/org/ oneOf выберет 1, someOf выберет 0-n, atLeastOne выберет 1-n и pick выберет любой номер, который вы укажете. - person Charles; 07.05.2017
comment
Большое спасибо, Джубобс, тогда Gen.pick :-) - person bugfoot; 07.05.2017