如何从Scala中的Set获取随机元素

问题描述 投票:18回答:7

例如,对于任何给定的集合,

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

如何从fruits获取随机元素?

非常感谢。

scala random collections set scala-collections
7个回答
19
投票

转换为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

17
投票

因此,之前发布的每个答案在空间方面都有复杂度O(n),因为它们以某种方式创建了整个集合的副本。这是一个没有任何额外复制的解决方案(因此它是“恒定空间”):

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

2
投票

您可以使用切片直接访问Set的元素。当我使用一个大小正在变化的集合时,我使用了这个,因此每次将它转换为Vector都显得有些过分。

val roll = new Random ()

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

2
投票

解决方法1

随机方式(import scala.util.Random

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

溶液2

数学方式(无进口)

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

1
投票
   import Scala.util.Random

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

   val sz =fruits.size

   val num = Random.nextInt(sz)

   fruits(num)

1
投票

从这个问题的其他答案中汲取灵感,我想出了:

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


0
投票

不将Set转换为有序集合,但使用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

0
投票

如果你不介意O(n)解决方案:

import util.Random

// val fruits = Set("apple", "grape", "pear", "banana")
Random.shuffle(fruits).head
// "pear"
© www.soinside.com 2019 - 2024. All rights reserved.