たとえば、任意のセットについて、
val fruits = Set("Apple", "grape", "pear", "banana")
fruits
からランダムな要素を取得する方法
どうもありがとう。
Vector
に変換し、そこからランダムな要素を取得します
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
したがって、以前に投稿されたすべての回答は、スペースの観点から複雑O(n)です。これは、何らかの方法でコレクション全体のコピーを作成するためです。以下は、追加のコピーを行わないソリューションです(したがって、「一定のスペース」です)。
def random[T](s: Set[T]): T = {
val n = util.Random.nextInt(s.size)
s.iterator.drop(n).next
}
スライスを持つセットの要素に直接アクセスできます。サイズが変化するセットで作業しているときにこれを使用したため、毎回ベクターに変換するのはやり過ぎのようでした。
val roll = new Random ()
val n = roll nextInt (fruits size)
fruits slice (n, n + 1) last
Solution1
ランダムな方法(import scala.util.Random
)
scala> fruits.toList(Random.nextInt(fruits.size))
res0: Java.lang.String = banana
Solution2
数学の方法(インポートなし)
scala> fruits.toList((math.random*fruits.size).toInt)
res1: String = banana
この質問に対する他の回答からインスピレーションを得て、私は次のことを思いつきました。
private def randomItem[T](items: Traversable[T]): Option[T] = {
val i = Random.nextInt(items.size)
items.view(i, i + 1).headOption
}
これは何もコピーせず、Set
(または他のタイプのTraversable
)が空の場合でも失敗せず、一目でそれが何をするかが一目でわかります。 Set
が空でないことが確実な場合は、.head
を代わりに使用してT
を返すことができます。
import Scala.util.Random
val fruits = Set("Apple", "grape", "pear", "banana").toVector
val sz =fruits.size
val num = Random.nextInt(sz)
fruits(num)
O(n)
ソリューションを気にしない場合:
import util.Random
// val fruits = Set("Apple", "grape", "pear", "banana")
Random.shuffle(fruits).head
// "pear"
Set
をorderedコレクションに変換するのではなく、zipWithIndex
を使用して、コレクション内の各アイテムにインデックスを割り当てることができます。
_fruits.zipWithIndex
Set((Apple,0), (grape,1), (pear,2), (banana,3))
_
したがって、val rnd = util.Random.nextInt(fruits.size)
の場合、
_fruits.zipWithIndex.find( _._2 == rnd)
Option[(String, Int)] = Some((banana,3))
_
空のセットを考えると、
_Set[String]().zipWithIndex.find( _._2 == 3)
Option[(String, Int)] = None
_