Skip to content

Instantly share code, notes, and snippets.

@joshlemer
Created June 10, 2017 21:21
Show Gist options
  • Save joshlemer/62760b50225a0051b7b205d9f03fa82d to your computer and use it in GitHub Desktop.
Save joshlemer/62760b50225a0051b7b205d9f03fa82d to your computer and use it in GitHub Desktop.
implicit class ChooseImplTraversable[T[X] <: TraversableLike[X, T[X]], A](val traversableLike: T[A])
extends AnyVal { //with Choose[T, A]{
def choose(n: Int)(implicit bf: CanBuildFrom[T[A], A, T[A]]): T[A] = {
if (n <= 0) {
bf().result()
} else {
val size = traversableLike.size
val resultSize = size min n
if (resultSize >= size) {
traversableLike
} else if (resultSize == 1) {
(bf() += traversableLike.toIterator.drop(Random.nextInt(size)).next()).result()
} else {
val b = {
val b = bf(traversableLike)
b.sizeHint(resultSize)
b
}
val iter = traversableLike.toIterator
var stillNeeded = resultSize
var remainingInIterator = size
while (stillNeeded > 0) {
val e = iter.next()
if (Random.nextInt(remainingInIterator) < stillNeeded) {
b += e
stillNeeded -= 1
}
remainingInIterator -= 1
}
b.result
}
}
}
}
implicit class ChooseImpl[T[X] <: SeqLike[X, T[X]], A](val seqLike: T[A])
extends AnyVal with Choose[T, A]{
def choose(n: Int)(implicit bf: CanBuildFrom[T[A], A, T[A]]): T[A] = {
if (n <= 0) {
bf().result()
} else {
val size = seqLike.size
val resultSize = size min n
if (resultSize >= size) {
seqLike
} else {
val b = {
val b = bf(seqLike)
b.sizeHint(resultSize)
b
}
val iter = seqLike.iterator
var stillNeeded = resultSize
var remainingInIterator = size
while (stillNeeded > 0) {
val e = iter.next()
if (Random.nextInt(remainingInIterator) < stillNeeded) {
b += e
stillNeeded -= 1
}
remainingInIterator -= 1
}
b.result
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment