How to choose a random element from an array in Scala?

ScalaScala 2.8

Scala Problem Overview


For example, there is a Scala array val A = Array("please", "help", "me"). How to choose a random element from this array?

Scala Solutions


Solution 1 - Scala

import scala.util.Random

val A = Array("please", "help", "me")
Random.shuffle(A.toList).head

Solution 2 - Scala

import scala.util.Random

val A = List(1, 2, 3, 4, 5, 6)
A(Random.nextInt(A.size))

Solution 3 - Scala

import java.util.Random
// ...
val rand = new Random(System.currentTimeMillis())
val random_index = rand.nextInt(A.length)
val result = A(random_index)

Solution 4 - Scala

We can also add some safety with the Option monad (using the lift method)

Actually, when using this method on any collection, even if your collection is empty, or your random index is out of boundaries, your result will always be an Option.

Drive safe <3
def getRandElemO[T](arr: Array[T]): Option[T] =
  if (arr.isEmpty) None
  else arr.lift(util.Random.nextInt(arr.length))

// or the one liner:
// def getRandElemO[T](arr: Array[T]): Option[T] =
//   arr.headOption.flatMap(_ => arr.lift(util.Random.nextInt(arr.length)))

Solution 5 - Scala

A better answer that does not involve reshuffling the array at all would be this:

import scala.util.Random

object sample {
  //gets random element from array
  def arr[T](items:Array[T]):T = {
    items(Random.nextInt(items.length))
  }
}

This also works generically

Solution 6 - Scala

If you want a more idiomatic solution, consider using the typeclass pattern (implicit classes in scala).

implicit class ListOps[A](list: List[A]) {
  def getRandomElement: Option[A] = list match {
    case Nil => None
    case _ => list.lift(scala.util.Random.nextInt(list.size))
  }
  def randomChoice(n: Int): Option[List[A]] =
    (1 to n).toList.foldLeft(Option(List[A]()))((acc, e) => getRandomElement.flatMap(r => acc.map(a => a :+ r)))
}

Now if the implicit class is in scope, you can:

val randomElement: Option[String] = List("this", "is", "a", "list").getRandomElement

If you are sure that the option contains some value, you can use the get method.

randomElement.get // This will return a String (or a NotSuchElementExeption)

Nonetheless, pattern matching or getOrElse are recommended:

randomElement match {
  case None => ??? // This is what you do when a None is encounter (e.g. for empty lists)
  case Some(result) => ??? // The variable result contains a string. 

Note that the randomChoice method assumes substitution of elements.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsamView Question on Stackoverflow
Solution 1 - Scalauser1338062View Answer on Stackoverflow
Solution 2 - ScalaahogueView Answer on Stackoverflow
Solution 3 - ScalatoplessView Answer on Stackoverflow
Solution 4 - ScalaRaphael BobillotView Answer on Stackoverflow
Solution 5 - ScalaJosh WeinsteinView Answer on Stackoverflow
Solution 6 - ScalaRodrigo Hernández MotaView Answer on Stackoverflow