Как выбрать случайный элемент из массива в Scala?

Например, есть массив Scala val A = Array("please", "help", "me"). Как выбрать случайный элемент из этого массива?


person sam    schedule 19.02.2011    source источник


Ответы (6)


Мы также можем добавить немного безопасности с помощью монады Option (используя метод lift)

Фактически, при использовании этого метода в любой коллекции, даже если ваша коллекция пуста или ваш случайный индекс выходит за границы, вашим результатом всегда будет Option.

Безопасное вождение ‹3

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

// or the one liner:
// def getRandElemO[T](arr: Array[T]): Option[T] =
//   arr.headOption.flatMap(_ => arr.lift(util.Random.nextInt(arr.length)))
person Raphael Bobillot    schedule 08.09.2017
comment
Обратите внимание, что это технически непрозрачно, поскольку два вызова с одним и тем же параметром не дадут одинаковый результат. Для этого вам также необходимо передать экземпляр RNG в params. - person Drestin; 13.01.2020

Лучшим ответом, который вообще не требует перетасовки массива, будет следующий:

import scala.util.Random

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

Это также работает в целом

person Josh Weinstein    schedule 20.05.2017
comment
Рассмотрим sample.arr [Int] (Array [Int] ()) - person Shiv4nsh; 27.11.2018

Если вам нужно более идиоматическое решение, рассмотрите возможность использования шаблона классов типов (неявные классы в 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 предполагает замену элементов.

person Rodrigo Hernández Mota    schedule 12.06.2018

person    schedule
comment
Хотя цель здесь - небезопасная псевдослучайность, это плохая практика - самозагрузить ГСЧ, если вы действительно, действительно не знаете, что делаете. Установка на текущее время особенно плохо, поскольку она значительно сужает окно возможных семян. Для получения дополнительной информации см. Эту серию: jazzy.id.au/default/2010 / 09/20 / - person Jed Wesley-Smith; 13.02.2012
comment
scala.util.Random имеет перемешивание, что намного проще, особенно если вам нужно несколько случайных элементов. См. Ответ ниже. - person user1338062; 02.02.2013
comment
это приведет к сбою, если A.length равно нулю. Никогда не забывайте о крайних случаях - person George Pligoropoulos; 11.06.2014
comment
Этот крайний случай является неотъемлемой частью требования. - person Elazar; 11.10.2015

person    schedule
comment
Эффективно ли переупорядочить весь список и выбрать заголовок, чем просто выбрать в O (1) значение массива? - person topless; 04.02.2013
comment
c2.com/cgi/wiki?PrematureOptimization Вопрос не указывает какие-либо потребности в эффективности, и на самом деле дает пример очень короткого массива :) - person user1338062; 04.02.2013
comment
Почему это должно быть временно? Он работает и менее подвержен ошибкам кодирования в границах массива. - person ashley; 15.01.2014
comment
Должно быть headOption, поскольку Seq (здесь Array) может быть пустым. - person Colin Woodbury; 01.08.2014
comment
А не пусто. Он состоит из трех струн. - person nkconnor; 12.01.2017

person    schedule
comment
это приведет к сбою, если A.size равно нулю. Никогда не забывайте о крайних случаях - person George Pligoropoulos; 11.06.2014
comment
О, вы можете использовать A.lift(Random.nextInt(A.size)), что даст вам Option[Int] - person Jon Onstott; 06.04.2015
comment
@JonOnstott также выйдет из строя, если A.size равно 0 - person 7kemZmani; 14.02.2018