How to get a random element from a Set in Scala
Drawing inspiration from the other answers to this question, I've come up with:
private def randomItem[T](items: Traversable[T]): Option[T] = {
val i = Random.nextInt(items.size)
items.view(i, i + 1).headOption
}
This doesn't copy anything, doesn't fail if the Set
(or other type of Traversable
) is empty, and it's clear at a glance what it does. If you're certain that the Set
is not empty, you could use .head
instead of headOption
, returning a T
.
So, every answer posted before has complexity O(n) in terms of space, since they create a copy a whole collection in some way. Here is a solution without any additional copying (therefore it is "constant space"):
def random[T](s: Set[T]): T = {
val n = util.Random.nextInt(s.size)
s.iterator.drop(n).next
}
convert into Vector
and get random element from it
scala> val fruits = Set("apple", "grape", "pear", "banana")
fruits: scala.collection.immutable.Set[String] = Set(apple, grape, pear, banana)
scala> import scala.util.Random
import scala.util.Random
scala> val rnd=new Random
rnd: scala.util.Random = scala.util.Random@31a9253
scala> fruits.toVector(rnd.nextInt(fruits.size))
res8: String = apple