Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a random element from a Set in Scala

For any given set, for instance,

val fruits = Set("apple", "grape", "pear", "banana")

how to get a random element from fruits ?

Many Thanks.

like image 723
elm Avatar asked Jul 31 '14 08:07

elm


3 Answers

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
like image 62
Govind Singh Avatar answered Nov 13 '22 13:11

Govind Singh


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
}
like image 30
Rok Kralj Avatar answered Nov 13 '22 11:11

Rok Kralj


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.

like image 3
László van den Hoek Avatar answered Nov 13 '22 13:11

László van den Hoek