it-swarm.com.de

So erhalten Sie ein zufälliges Element aus einem Set in Scala

Für eine bestimmte Menge, zum Beispiel,

val fruits = Set("Apple", "grape", "pear", "banana")

wie bekomme ich ein zufälliges Element aus fruits?

Danke vielmals.

16
elm

konvertiere in Vector und erhalte ein zufälliges Element daraus

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 = [email protected]

scala> fruits.toVector(rnd.nextInt(fruits.size))
res8: String = Apple
18
Govind Singh

Jede Antwort, die zuvor gepostet wurde, ist also O(n) in Bezug auf den Platz komplex, da sie auf irgendeine Weise eine Kopie einer gesamten Sammlung erstellen. Hier ist eine Lösung ohne zusätzliches Kopieren (daher ist es "konstanter Raum"):

def random[T](s: Set[T]): T = {
  val n = util.Random.nextInt(s.size)
  s.iterator.drop(n).next
}
17
Rok Kralj

Sie können direkt auf ein Element eines Sets mit Slice zugreifen. Ich habe dies verwendet, als ich mit einem Set gearbeitet habe, dessen Größe sich geändert hat, sodass es mir jedes Mal wie ein Overkill vorkam, es in einen Vector umzuwandeln.

val roll = new Random ()

val n = roll nextInt (fruits size)
fruits slice (n, n + 1) last
2
Wayne

Solution1

Zufälliger Weg (import scala.util.Random)

scala>  fruits.toList(Random.nextInt(fruits.size))
res0: Java.lang.String = banana

Solution2

Mathe Weg (keine Importe)

scala> fruits.toList((math.random*fruits.size).toInt)
res1: String = banana
2
AmeyChavan

Ich habe mich von den anderen Antworten auf diese Frage inspirieren lassen und mir Folgendes ausgedacht:

private def randomItem[T](items: Traversable[T]): Option[T] = {
  val i = Random.nextInt(items.size)
  items.view(i, i + 1).headOption
}

Dies kopiert nichts, schlägt nicht fehl, wenn die Set (oder eine andere Art von Traversable) leer ist, und es ist auf einen Blick klar, was sie tut. Wenn Sie sicher sind, dass die Set nicht leer ist, können Sie .head ersetzen und stattdessen T zurückgeben.

   import Scala.util.Random

   val fruits = Set("Apple", "grape", "pear", "banana").toVector

   val sz =fruits.size

   val num = Random.nextInt(sz)

   fruits(num)
1
Ashalynd

Wenn Ihnen eine O(n) Lösung nichts ausmacht:

import util.Random

// val fruits = Set("Apple", "grape", "pear", "banana")
Random.shuffle(fruits).head
// "pear"
0
Xavier Guihot

Wir konvertieren die Set nicht in eine geordnete Sammlung, sondern verwenden zipWithIndex, um jedem Element in der Sammlung einen Index zuzuweisen.

fruits.zipWithIndex
Set((Apple,0), (grape,1), (pear,2), (banana,3))

Also für val rnd = util.Random.nextInt(fruits.size),

fruits.zipWithIndex.find( _._2 == rnd)
Option[(String, Int)] = Some((banana,3))

Bei einer leeren Menge

Set[String]().zipWithIndex.find( _._2 == 3)
Option[(String, Int)] = None
0
elm