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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25053724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:27:45  来源:igfitidea点击:

How to get a random element from a Set in Scala

scalarandomcollectionssetscala-collections

提问by elm

For any given set, for instance,

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

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

how to get a random element from fruits?

如何从中获取随机元素fruits

Many Thanks.

非常感谢。

采纳答案by Govind Singh

convert into Vectorand get random element from it

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

回答by Rok Kralj

So, every answer posted before has complexity O(n) in terms of space,since they create a copy a whole collection in some way. Here is a solution without any additional copying (therefore it is "constant space"):

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

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

回答by Wayne

You can directly access an element of a Set with slice. I used this when I was working with a set that was changing in size, so converting it to a Vector every time seemed like overkill.

您可以使用切片直接访问 Set 的元素。我在处理大小不断变化的集合时使用了它,因此每次将其转换为 Vector 似乎有点矫枉过正。

val roll = new Random ()

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

回答by László van den Hoek

Drawing inspiration from the other answers to this question, I've come up with:

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

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

This doesn't copy anything, doesn't fail if the Set(or other type of Traversable) is empty, and it's clear at a glance what it does. If you're certain that the Setis not empty, you could use .headinstead of headOption, returning a T.

这不会复制任何内容,如果Set( 或其他类型的Traversable) 为空也不会失败,而且它的作用一目了然。如果您确定Set不为空,则可以使用.head代替headOption,返回一个T

回答by AmeyChavan

Solution1

解决方案1

Random way ( import scala.util.Random)

随机方式 ( import scala.util.Random)

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

Solution2

解决方案2

Math way (no imports)

数学方式(无进口)

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

回答by Ashalynd

   import Scala.util.Random

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

   val sz =fruits.size

   val num = Random.nextInt(sz)

   fruits(num)

回答by elm

Not converting the Setto an orderedcollection but using zipWithIndexwe can attribute an index to each item in the collection,

不是将 转换Set有序集合,而是使用zipWithIndex我们可以为集合中的每个项目分配一个索引,

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

Thus for val rnd = util.Random.nextInt(fruits.size),

因此对于val rnd = util.Random.nextInt(fruits.size)

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

Given an empty set,

给定一个空集,

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

回答by Xavier Guihot

If you don't mind an O(n)solution:

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

import util.Random

// val fruits = Set("apple", "grape", "pear", "banana")
Random.shuffle(fruits).head
// "pear"