web-dev-qa-db-ja.com

Scalaの配列からランダムな要素を選択する方法は?

たとえば、Scala array val A = Array("please", "help", "me")。があります。この配列からランダムな要素を選択する方法は?

47
sam
import Java.util.Random
// ...
val Rand = new Random(System.currentTimeMillis())
val random_index = Rand.nextInt(A.length)
val result = A(random_index)
36
topless
import scala.util.Random

val A = Array("please", "help", "me")
Random.shuffle(A.toList).head
92
user1338062
import scala.util.Random

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

Optionモナドを使用して安全性を追加することもできます(lift関数と条件を使用)

実際、この関数を配列(空の場合もあります)で使用すると、結果は常にオプションになります。

参照透明度FTW\o /

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

より慣用的なソリューションが必要な場合は、typeclassパターン(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)))
}

暗黙のクラスがスコープ内にある場合、次のことができます。

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. 

randomChoiceメソッドは要素の置換を想定しています。

配列の入れ替えをまったく伴わないより良い答えは、次のとおりです。

import scala.util.Random

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

これも一般的に機能します

0
Josh Weinstein