For example, there is a Scala array val A = Array("please", "help", "me")
. How to choose a random element from this array?
Asked
Active
Viewed 4.9k times
6 Answers
94
import scala.util.Random
val A = Array("please", "help", "me")
Random.shuffle(A.toList).head

user1338062
- 11,939
- 3
- 73
- 67
-
24is it efficient to re-order the whole list and pick the head than just picking in O(1) a value of the array? – topless Feb 04 '13 at 17:53
-
5http://c2.com/cgi/wiki?PrematureOptimization The question does not specify any efficiency needs, and actually gives an example of a very short Array :) – user1338062 Feb 04 '13 at 19:36
-
4Why should it be temporary? It works, and is less prone to any coding error in the array bounds. – ashley Jan 14 '14 at 23:39
-
8Ought to be `headOption`, since the `Seq` (`Array` here) might be empty. – Colin Woodbury Aug 01 '14 at 00:00
-
5A is not empty. It contains three strings. – nkconnor Jan 12 '17 at 14:49
43
import scala.util.Random
val A = List(1, 2, 3, 4, 5, 6)
A(Random.nextInt(A.size))

ahogue
- 547
- 4
- 3
-
16this will crash if `A.size` equals to zero. Never forget about edge cases – George Pligoropoulos Jun 11 '14 at 09:42
-
5Oh, you can use `A.lift(Random.nextInt(A.size))` which will give you `Option[Int]` – Jon Onstott Apr 06 '15 at 02:37
-
1
38
import java.util.Random
// ...
val rand = new Random(System.currentTimeMillis())
val random_index = rand.nextInt(A.length)
val result = A(random_index)

DaMainBoss
- 2,035
- 1
- 19
- 26

topless
- 8,069
- 11
- 57
- 86
-
31while the purpose here is insecure pseudo-randomness, it is bad practice to self-seed a RNG unless you really, really know what you are doing. Setting to current time is particularly bad as it significantly narrows the window of possible seeds. For more info see this series: http://jazzy.id.au/default/2010/09/20/cracking_random_number_generators_part_1.html – Jed Wesley-Smith Feb 12 '12 at 21:29
-
1scala.util.Random has shuffle, which is much simpler, especially if you need multiple random elements. See answer below. – user1338062 Feb 02 '13 at 16:45
-
11this will crash if `A.length` equals to zero. Never forget about edge cases – George Pligoropoulos Jun 11 '14 at 09:41
-
1
4
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)))

Raphael Bobillot
- 71
- 3
-
1Note that it is not technically referencially transparent since two calls with the same parameter won't give the same result. To achieve this you would have to pass the RNG instance in params as well. – Drestin Jan 13 '20 at 16:48
1
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

Josh Weinstein
- 2,788
- 2
- 21
- 38
1
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.

Rodrigo Hernández Mota
- 131
- 1
- 5