如何在Scala中从数组中选择随机元素?

如何在Scala中从数组中选择随机元素?,scala,scala-2.8,Scala,Scala 2.8,例如,有一个Scala数组vala=array(“请”、“帮助”、“我”)。如何从这个数组中选择一个随机元素?一个更好的答案是,根本不需要重新排列数组: import java.util.Random // ... val rand = new Random(System.currentTimeMillis()) val random_index = rand.nextInt(A.length) val result = A(random_index) import scala.util.Ra

例如,有一个Scala数组
vala=array(“请”、“帮助”、“我”)
。如何从这个数组中选择一个随机元素?

一个更好的答案是,根本不需要重新排列数组:

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

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

这也适用于一般情况

我们还可以使用
选项
monad(使用
提升
方法)增加一些安全性

实际上,在任何集合上使用此方法时, 即使您的集合为空,或者您的随机索引超出边界,您的结果也将始终是一个选项


如果你想要一个更惯用的解决方案,考虑使用Type CelpScript模式(Scala中的隐式类)。 现在,如果隐式类在范围内,您可以:

val randomElement: Option[String] = List("this", "is", "a", "list").getRandomElement
如果确定该选项包含某些值,则可以使用
get
方法

randomElement.get // This will return a String (or a NotSuchElementExeption)
尽管如此,还是建议使用模式匹配或
getOrElse

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. 

注意随机选择方法假定替换元素

虽然这里的目的是不安全的伪随机性,但除非你真的,真的知道你在做什么,否则自我植入RNG是不好的做法。设置为“当前时间”尤其糟糕,因为它大大缩小了可能的种子窗口。有关更多信息,请参阅本系列:scala.util.Random具有shuffle,这非常简单,特别是当您需要多个随机元素时。请参阅下面的答案。如果
A.length
等于零,则此操作将崩溃。永远不要忘记边缘情况此边缘情况是需求中固有的。重新排列整个列表并选择头部是否比仅选择数组的O(1)值有效?这个问题没有具体说明任何效率需求,实际上给出了一个非常短的数组的示例:)为什么它应该是临时的?它可以工作,并且在数组边界中不太容易出现任何编码错误。应该是
headOption
,因为
Seq
array
)可能是空的。A不是空的。它包含三个字符串。如果
A.size
等于零,则会崩溃。永远不要忘记edge CaseSh,您可以使用
A.lift(Random.nextInt(A.size))
它将为您提供
选项[Int]
@JonOnstott如果
A.size
是0考虑样本,也会崩溃。arr[Int](数组[Int]())请注意,它在技术上不是透明的,因为使用相同参数的两个调用不会给出相同的结果。要实现这一点,还必须在params中传递RNG实例。
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)))
}
val randomElement: Option[String] = List("this", "is", "a", "list").getRandomElement
randomElement.get // This will return a String (or a NotSuchElementExeption)
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.